xref: /illumos-gate/usr/src/uts/intel/io/vmxnet3s/vmxnet3_utils.c (revision 5626beece2e5dedec7197ecf325cfaa1854a6c2e)
1 /*
2  * Copyright (C) 2007 VMware, Inc. All rights reserved.
3  *
4  * The contents of this file are subject to the terms of the Common
5  * Development and Distribution License (the "License") version 1.0
6  * and no later version.  You may not use this file except in
7  * compliance with the License.
8  *
9  * You can obtain a copy of the License at
10  *         http://www.opensource.org/licenses/cddl1.php
11  *
12  * See the License for the specific language governing permissions
13  * and limitations under the License.
14  */
15 
16 #include <vmxnet3.h>
17 
18 /* Used by ddi_regs_map_setup() and ddi_dma_mem_alloc() */
19 ddi_device_acc_attr_t vmxnet3_dev_attr = {
20 	DDI_DEVICE_ATTR_V0,
21 	DDI_STRUCTURE_LE_ACC,
22 	DDI_STRICTORDER_ACC
23 };
24 
25 /* Buffers with no alignment constraint DMA description */
26 static ddi_dma_attr_t vmxnet3_dma_attrs_1 = {
27 	.dma_attr_version =	DMA_ATTR_V0,
28 	.dma_attr_addr_lo =	0x0000000000000000ull,
29 	.dma_attr_addr_hi =	0xFFFFFFFFFFFFFFFFull,
30 	.dma_attr_count_max =	0xFFFFFFFFFFFFFFFFull,
31 	.dma_attr_align =	0x0000000000000001ull,
32 	.dma_attr_burstsizes =	0x0000000000000001ull,
33 	.dma_attr_minxfer =	0x00000001,
34 	.dma_attr_maxxfer =	0xFFFFFFFFFFFFFFFFull,
35 	.dma_attr_seg =		0xFFFFFFFFFFFFFFFFull,
36 	.dma_attr_sgllen =	1,
37 	.dma_attr_granular =	0x00000001,
38 	.dma_attr_flags =	0
39 };
40 
41 /* Buffers with a 128-bytes alignment constraint DMA description */
42 static ddi_dma_attr_t vmxnet3_dma_attrs_128 = {
43 	.dma_attr_version =	DMA_ATTR_V0,
44 	.dma_attr_addr_lo =	0x0000000000000000ull,
45 	.dma_attr_addr_hi =	0xFFFFFFFFFFFFFFFFull,
46 	.dma_attr_count_max =	0xFFFFFFFFFFFFFFFFull,
47 	.dma_attr_align =	0x0000000000000080ull,
48 	.dma_attr_burstsizes =	0x0000000000000001ull,
49 	.dma_attr_minxfer =	0x00000001,
50 	.dma_attr_maxxfer =	0xFFFFFFFFFFFFFFFFull,
51 	.dma_attr_seg =		0xFFFFFFFFFFFFFFFFull,
52 	.dma_attr_sgllen =	1,
53 	.dma_attr_granular =	0x00000001,
54 	.dma_attr_flags =	0
55 };
56 
57 /* Buffers with a 512-bytes alignment constraint DMA description */
58 static ddi_dma_attr_t vmxnet3_dma_attrs_512 = {
59 	.dma_attr_version =	DMA_ATTR_V0,
60 	.dma_attr_addr_lo =	0x0000000000000000ull,
61 	.dma_attr_addr_hi =	0xFFFFFFFFFFFFFFFFull,
62 	.dma_attr_count_max =	0xFFFFFFFFFFFFFFFFull,
63 	.dma_attr_align =	0x0000000000000200ull,
64 	.dma_attr_burstsizes =	0x0000000000000001ull,
65 	.dma_attr_minxfer =	0x00000001,
66 	.dma_attr_maxxfer =	0xFFFFFFFFFFFFFFFFull,
67 	.dma_attr_seg =		0xFFFFFFFFFFFFFFFFull,
68 	.dma_attr_sgllen =	1,
69 	.dma_attr_granular =	0x00000001,
70 	.dma_attr_flags =	0
71 };
72 
73 /*
74  * vmxnet3_alloc_dma_mem --
75  *
76  *    Allocate /size/ bytes of contiguous DMA-ble memory.
77  *
78  * Results:
79  *    DDI_SUCCESS or DDI_FAILURE.
80  *
81  * Side effects:
82  *    None.
83  */
84 static int
85 vmxnet3_alloc_dma_mem(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, size_t size,
86     boolean_t canSleep, ddi_dma_attr_t *dma_attrs)
87 {
88 	ddi_dma_cookie_t cookie;
89 	uint_t cookieCount;
90 	int (*cb) (caddr_t) = canSleep ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT;
91 
92 	ASSERT(size != 0);
93 
94 	/*
95 	 * Allocate a DMA handle
96 	 */
97 	if (ddi_dma_alloc_handle(dp->dip, dma_attrs, cb, NULL,
98 	    &dma->dmaHandle) != DDI_SUCCESS) {
99 		VMXNET3_WARN(dp, "ddi_dma_alloc_handle() failed\n");
100 		goto error;
101 	}
102 
103 	/*
104 	 * Allocate memory
105 	 */
106 	if (ddi_dma_mem_alloc(dma->dmaHandle, size, &vmxnet3_dev_attr,
107 	    DDI_DMA_CONSISTENT, cb, NULL, &dma->buf, &dma->bufLen,
108 	    &dma->dataHandle) != DDI_SUCCESS) {
109 		VMXNET3_WARN(dp, "ddi_dma_mem_alloc() failed\n");
110 		goto error_dma_handle;
111 	}
112 
113 	/*
114 	 * Map the memory
115 	 */
116 	if (ddi_dma_addr_bind_handle(dma->dmaHandle, NULL, dma->buf,
117 	    dma->bufLen, DDI_DMA_RDWR | DDI_DMA_STREAMING, cb, NULL, &cookie,
118 	    &cookieCount) != DDI_DMA_MAPPED) {
119 		VMXNET3_WARN(dp, "ddi_dma_addr_bind_handle() failed\n");
120 		goto error_dma_mem;
121 	}
122 
123 	ASSERT(cookieCount == 1);
124 	dma->bufPA = cookie.dmac_laddress;
125 
126 	return (DDI_SUCCESS);
127 
128 error_dma_mem:
129 	ddi_dma_mem_free(&dma->dataHandle);
130 error_dma_handle:
131 	ddi_dma_free_handle(&dma->dmaHandle);
132 error:
133 	dma->buf = NULL;
134 	dma->bufPA = NULL;
135 	dma->bufLen = 0;
136 	return (DDI_FAILURE);
137 }
138 
139 int
140 vmxnet3_alloc_dma_mem_1(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma, size_t size,
141     boolean_t canSleep)
142 {
143 	return (vmxnet3_alloc_dma_mem(dp, dma, size, canSleep,
144 	    &vmxnet3_dma_attrs_1));
145 }
146 
147 int
148 vmxnet3_alloc_dma_mem_512(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma,
149     size_t size, boolean_t canSleep)
150 {
151 	return (vmxnet3_alloc_dma_mem(dp, dma, size, canSleep,
152 	    &vmxnet3_dma_attrs_512));
153 }
154 
155 int
156 vmxnet3_alloc_dma_mem_128(vmxnet3_softc_t *dp, vmxnet3_dmabuf_t *dma,
157     size_t size, boolean_t canSleep)
158 {
159 	return (vmxnet3_alloc_dma_mem(dp, dma, size, canSleep,
160 	    &vmxnet3_dma_attrs_128));
161 }
162 
163 /*
164  * vmxnet3_free_dma_mem --
165  *
166  *    Free DMA-ble memory.
167  *
168  * Results:
169  *    None.
170  *
171  * Side effects:
172  *    None.
173  */
174 void
175 vmxnet3_free_dma_mem(vmxnet3_dmabuf_t *dma)
176 {
177 	(void) ddi_dma_unbind_handle(dma->dmaHandle);
178 	ddi_dma_mem_free(&dma->dataHandle);
179 	ddi_dma_free_handle(&dma->dmaHandle);
180 
181 	dma->buf = NULL;
182 	dma->bufPA = NULL;
183 	dma->bufLen = 0;
184 }
185 
186 /*
187  * vmxnet3_getprop --
188  *
189  *    Get the numeric value of the property "name" in vmxnet3s.conf for
190  *    the corresponding device instance.
191  *    If the property isn't found or if it doesn't satisfy the conditions,
192  *    "def" is returned.
193  *
194  * Results:
195  *    The value of the property or "def".
196  *
197  * Side effects:
198  *    None.
199  */
200 int
201 vmxnet3_getprop(vmxnet3_softc_t *dp, char *name, int min, int max, int def)
202 {
203 	int ret = def;
204 	int *props;
205 	uint_t nprops;
206 
207 	if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dp->dip, DDI_PROP_DONTPASS,
208 	    name, &props, &nprops) == DDI_PROP_SUCCESS) {
209 		if (dp->instance < nprops) {
210 			ret = props[dp->instance];
211 		} else {
212 			VMXNET3_WARN(dp, "property %s not available for this "
213 			    "device\n", name);
214 		}
215 		ddi_prop_free(props);
216 	}
217 
218 	if (ret < min || ret > max) {
219 		ASSERT(def >= min && def <= max);
220 		VMXNET3_WARN(dp, "property %s invalid (%d <= %d <= %d)\n",
221 		    name, min, ret, max);
222 		ret = def;
223 	}
224 
225 	VMXNET3_DEBUG(dp, 2, "getprop(%s) -> %d\n", name, ret);
226 
227 	return (ret);
228 }
229