2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /* Copyright © 2003-2011 Emulex. All rights reserved. */
23
24 /*
25 * Source file containing the implementation of Driver buffer management
26 * and related helper functions
27 */
28 #include <oce_impl.h>
29
30 static ddi_dma_attr_t oce_dma_buf_attr = {
31 DMA_ATTR_V0, /* version number */
32 0x0000000000000000ull, /* low address */
33 0xFFFFFFFFFFFFFFFFull, /* high address */
34 0x00000000FFFFFFFFull, /* dma counter max */
35 OCE_DMA_ALIGNMENT, /* alignment */
36 0x00000FFF, /* burst sizes */
37 0x00000001, /* minimum transfer size */
38 0x00000000FFFFFFFFull, /* maximum transfer size */
39 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */
40 1, /* scatter/gather list length */
41 0x00000001, /* granularity */
42 0 /* DMA flags */
43 };
44
45 static ddi_device_acc_attr_t oce_dma_buf_accattr = {
46 DDI_DEVICE_ATTR_V0,
47 DDI_NEVERSWAP_ACC,
48 DDI_STRICTORDER_ACC,
49 };
50
51
52 /*
53 * function to allocate a dma buffer for mapping memory va-pa
54 *
55 * dev - software handle to device
56 * size - size of the memory to map
57 * flags - DDI_DMA_CONSISTENT/DDI_DMA_STREAMING
58 *
59 * return pointer to a oce_dma_buf_t structure handling the map
60 * NULL => failure
61 */
62 oce_dma_buf_t *
63 oce_alloc_dma_buffer(struct oce_dev *dev,
64 uint32_t size, ddi_dma_attr_t *dma_attr, uint32_t flags)
65 {
66 oce_dma_buf_t *dbuf;
67 ddi_dma_cookie_t cookie;
68 uint32_t count;
69 size_t actual_len;
70 int ret = 0;
71
72 ASSERT(size > 0);
73 /* if NULL use default */
74 if (dma_attr == NULL) {
75 dma_attr = &oce_dma_buf_attr;
76 }
77
78 dbuf = kmem_zalloc(sizeof (oce_dma_buf_t), KM_NOSLEEP);
79 if (dbuf == NULL) {
80 return (NULL);
81 }
82
83 /* allocate dma handle */
84 ret = ddi_dma_alloc_handle(dev->dip, dma_attr,
85 DDI_DMA_DONTWAIT, NULL, &dbuf->dma_handle);
86 if (ret != DDI_SUCCESS) {
87 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
88 "Failed to allocate DMA handle");
89 goto handle_fail;
90 }
91 /* allocate the DMA-able memory */
92 ret = ddi_dma_mem_alloc(dbuf->dma_handle, size, &oce_dma_buf_accattr,
93 flags, DDI_DMA_DONTWAIT, NULL, &dbuf->base,
94 &actual_len, &dbuf->acc_handle);
95 if (ret != DDI_SUCCESS) {
96 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
97 "Failed to allocate DMA memory");
98 goto alloc_fail;
99 }
100
101 /* bind handle */
102 ret = ddi_dma_addr_bind_handle(dbuf->dma_handle,
103 (struct as *)0, dbuf->base, actual_len,
104 DDI_DMA_RDWR | flags,
105 DDI_DMA_DONTWAIT, NULL, &cookie, &count);
106 if (ret != DDI_DMA_MAPPED) {
107 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
108 "Failed to bind dma handle");
109 goto bind_fail;
110 }
111 bzero(dbuf->base, actual_len);
112 dbuf->addr = cookie.dmac_laddress;
113 dbuf->size = actual_len;
114 /* usable length */
115 dbuf->len = size;
116 dbuf->num_pages = OCE_NUM_PAGES(size);
117 return (dbuf);
118
119 bind_fail:
120 ddi_dma_mem_free(&dbuf->acc_handle);
121 alloc_fail:
122 ddi_dma_free_handle(&dbuf->dma_handle);
123 handle_fail:
124 kmem_free(dbuf, sizeof (oce_dma_buf_t));
125 return (NULL);
126 } /* oce_dma_alloc_buffer */
127
128 /*
129 * function to delete a dma buffer
130 *
131 * dev - software handle to device
132 * dbuf - dma obj to delete
133 *
134 * return none
135 */
136 void
137 oce_free_dma_buffer(struct oce_dev *dev, oce_dma_buf_t *dbuf)
138 {
139 _NOTE(ARGUNUSED(dev));
140
141 if (dbuf == NULL) {
142 return;
143 }
144 if (dbuf->dma_handle != NULL) {
145 (void) ddi_dma_unbind_handle(dbuf->dma_handle);
146 }
147 if (dbuf->acc_handle != NULL) {
148 ddi_dma_mem_free(&dbuf->acc_handle);
149 }
150 if (dbuf->dma_handle != NULL) {
151 ddi_dma_free_handle(&dbuf->dma_handle);
152 }
153 kmem_free(dbuf, sizeof (oce_dma_buf_t));
154 } /* oce_free_dma_buffer */
155
156 /*
157 * function to create a ring buffer
158 *
159 * dev - software handle to the device
160 * num_items - number of items in the ring
161 * item_size - size of an individual item in the ring
162 * flags - DDI_DMA_CONSISTENT/DDI_DMA_STREAMING for ring memory
163 *
164 * return pointer to a ring_buffer structure, NULL on failure
165 */
166 oce_ring_buffer_t *
167 create_ring_buffer(struct oce_dev *dev,
168 uint32_t num_items, uint32_t item_size, uint32_t flags)
169 {
170 oce_ring_buffer_t *ring;
171 uint32_t size;
172
173 /* allocate the ring buffer */
174 ring = kmem_zalloc(sizeof (oce_ring_buffer_t), KM_NOSLEEP);
175 if (ring == NULL) {
176 return (NULL);
177 }
178
179 /* get the dbuf defining the ring */
180 size = num_items * item_size;
181 ring->dbuf = oce_alloc_dma_buffer(dev, size, NULL, flags);
182 if (ring->dbuf == NULL) {
183 oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
184 "Ring buffer allocation failed");
185 goto dbuf_fail;
186 }
187
188 /* fill the rest of the ring */
189 ring->num_items = num_items;
190 ring->item_size = item_size;
191 ring->num_used = 0;
192 return (ring);
193
194 dbuf_fail:
195 kmem_free(ring, sizeof (oce_ring_buffer_t));
196 return (NULL);
197 } /* create_ring_buffer */
198
199 /*
200 * function to destroy a ring buffer
201 *
202 * dev - software handle to teh device
203 * ring - the ring buffer to delete
204 *
205 * return none
206 */
207 void
208 destroy_ring_buffer(struct oce_dev *dev, oce_ring_buffer_t *ring)
209 {
210 ASSERT(dev != NULL);
211 ASSERT(ring != NULL);
212
213 /* free the dbuf associated with the ring */
214 oce_free_dma_buffer(dev, ring->dbuf);
215 ring->dbuf = NULL;
216
217 /* free the ring itself */
218 kmem_free(ring, sizeof (oce_ring_buffer_t));
219 } /* destroy_ring_buffer */
220
221
222 /*
223 * function to enable the fma flags
224 * fm_caps - FM capability flags
225 *
226 * return none
227 */
228
229 void
230 oce_set_dma_fma_flags(int fm_caps)
231 {
232 if (fm_caps == DDI_FM_NOT_CAPABLE) {
233 return;
234 }
235
|
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2009-2012 Emulex. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27
28 /*
29 * Source file containing the implementation of Driver buffer management
30 * and related helper functions
31 */
32 #include <oce_impl.h>
33
34 static ddi_dma_attr_t oce_dma_buf_attr = {
35 DMA_ATTR_V0, /* version number */
36 0x0000000000000000ull, /* low address */
37 0xFFFFFFFFFFFFFFFFull, /* high address */
38 0x00000000FFFFFFFFull, /* dma counter max */
39 OCE_DMA_ALIGNMENT, /* alignment */
40 0x00000FFF, /* burst sizes */
41 0x00000001, /* minimum transfer size */
42 0x00000000FFFFFFFFull, /* maximum transfer size */
43 0xFFFFFFFFFFFFFFFFull, /* maximum segment size */
44 1, /* scatter/gather list length */
45 0x00000001, /* granularity */
46 0 /* DMA flags */
47 };
48
49 static ddi_device_acc_attr_t oce_dma_buf_accattr = {
50 DDI_DEVICE_ATTR_V0,
51 DDI_NEVERSWAP_ACC,
52 DDI_STRICTORDER_ACC,
53 };
54
55
56 /*
57 * function to allocate a dma buffer for mapping memory va-pa
58 *
59 * dev - software handle to device
60 * size - size of the memory to map
61 * flags - DDI_DMA_CONSISTENT/DDI_DMA_STREAMING
62 *
63 * return pointer to a oce_dma_buf_t structure handling the map
64 * NULL => failure
65 */
66 int
67 oce_alloc_dma_buffer(struct oce_dev *dev, oce_dma_buf_t *dbuf,
68 uint32_t size, ddi_dma_attr_t *dma_attr, uint32_t flags)
69 {
70 size_t actual_len;
71 int ret = 0;
72
73 ASSERT(size > 0);
74 /* if NULL use default */
75 if (dma_attr == NULL) {
76 dma_attr = &oce_dma_buf_attr;
77 }
78
79 /* allocate dma handle */
80 ret = ddi_dma_alloc_handle(dev->dip, dma_attr,
81 DDI_DMA_DONTWAIT, NULL, &dbuf->dma_handle);
82 if (ret != DDI_SUCCESS) {
83 oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
84 "Failed to allocate DMA handle");
85 goto handle_fail;
86 }
87 /* allocate the DMA-able memory */
88 ret = ddi_dma_mem_alloc(dbuf->dma_handle, size, &oce_dma_buf_accattr,
89 (flags & DDI_DMA_STREAMING) ?
90 DDI_DMA_STREAMING : DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL,
91 &dbuf->base, &actual_len, &dbuf->acc_handle);
92 if (ret != DDI_SUCCESS) {
93 oce_log(dev, CE_NOTE, MOD_CONFIG,
94 "Failed to allocate DMA memory: 0x%x bytes", size);
95 goto alloc_fail;
96 }
97
98 /* bind handle */
99 ret = ddi_dma_addr_bind_handle(dbuf->dma_handle,
100 (struct as *)0, dbuf->base, actual_len,
101 flags,
102 DDI_DMA_DONTWAIT, NULL, &dbuf->cookie, &dbuf->ncookies);
103 if (ret != DDI_DMA_MAPPED) {
104 oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
105 "Failed to bind dma handle");
106 goto bind_fail;
107 }
108 bzero(dbuf->base, actual_len);
109 dbuf->addr = dbuf->cookie.dmac_laddress;
110 dbuf->size = actual_len;
111 /* usable length */
112 dbuf->len = size;
113 dbuf->num_pages = OCE_NUM_PAGES(size);
114 return (DDI_SUCCESS);
115
116 bind_fail:
117 ddi_dma_mem_free(&dbuf->acc_handle);
118 alloc_fail:
119 ddi_dma_free_handle(&dbuf->dma_handle);
120 handle_fail:
121 return (ret);
122 } /* oce_dma_alloc_buffer */
123
124 /*
125 * function to delete a dma buffer
126 *
127 * dev - software handle to device
128 * dbuf - dma obj to delete
129 *
130 * return none
131 */
132 void
133 oce_free_dma_buffer(struct oce_dev *dev, oce_dma_buf_t *dbuf)
134 {
135 _NOTE(ARGUNUSED(dev));
136
137 if (dbuf == NULL) {
138 return;
139 }
140 if (dbuf->dma_handle != NULL) {
141 (void) ddi_dma_unbind_handle(dbuf->dma_handle);
142 }
143 if (dbuf->acc_handle != NULL) {
144 ddi_dma_mem_free(&dbuf->acc_handle);
145 dbuf->acc_handle = NULL;
146 }
147 if (dbuf->dma_handle != NULL) {
148 ddi_dma_free_handle(&dbuf->dma_handle);
149 dbuf->dma_handle = NULL;
150 }
151 } /* oce_free_dma_buffer */
152
153 /*
154 * function to create a ring buffer
155 *
156 * dev - software handle to the device
157 * num_items - number of items in the ring
158 * item_size - size of an individual item in the ring
159 * flags - DDI_DMA_CONSISTENT/DDI_DMA_STREAMING for ring memory
160 *
161 * return pointer to a ring_buffer structure, NULL on failure
162 */
163 oce_ring_buffer_t *
164 oce_create_ring_buffer(struct oce_dev *dev,
165 uint32_t num_items, uint32_t item_size, uint32_t flags)
166 {
167 oce_ring_buffer_t *ring;
168 int ret;
169
170 /* allocate the ring buffer */
171 ring = kmem_zalloc(sizeof (oce_ring_buffer_t), KM_NOSLEEP);
172 if (ring == NULL) {
173 return (NULL);
174 }
175
176 /* get the dbuf defining the ring */
177 ret = oce_alloc_dma_buffer(dev, &ring->dbuf, num_items *item_size,
178 NULL, flags);
179 if (ret != DDI_SUCCESS) {
180 oce_log(dev, CE_WARN, MOD_CONFIG,
181 "Ring buffer allocation failed 0x%x", ret);
182 goto dbuf_fail;
183 }
184
185 /* fill the rest of the ring */
186 ring->num_items = num_items;
187 ring->item_size = item_size;
188 ring->num_used = 0;
189 return (ring);
190
191 dbuf_fail:
192 kmem_free(ring, sizeof (oce_ring_buffer_t));
193 return (NULL);
194 } /* create_ring_buffer */
195
196 /*
197 * function to destroy a ring buffer
198 *
199 * dev - software handle to teh device
200 * ring - the ring buffer to delete
201 *
202 * return none
203 */
204 void
205 destroy_ring_buffer(struct oce_dev *dev, oce_ring_buffer_t *ring)
206 {
207 ASSERT(dev != NULL);
208 ASSERT(ring != NULL);
209
210 /* free the dbuf associated with the ring */
211 oce_free_dma_buffer(dev, &ring->dbuf);
212
213 /* free the ring itself */
214 kmem_free(ring, sizeof (oce_ring_buffer_t));
215 } /* destroy_ring_buffer */
216
217
218 /*
219 * function to enable the fma flags
220 * fm_caps - FM capability flags
221 *
222 * return none
223 */
224
225 void
226 oce_set_dma_fma_flags(int fm_caps)
227 {
228 if (fm_caps == DDI_FM_NOT_CAPABLE) {
229 return;
230 }
231
|