1 /*
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 2008-2013 Solarflare Communications Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/types.h>
28 #include <sys/ddi.h>
29 #include <sys/sunddi.h>
30 #include <sys/stream.h>
31 #include <sys/dlpi.h>
32
33 #include "sfxge.h"
34
35 void
36 sfxge_sram_init(sfxge_t *sp)
37 {
38 sfxge_sram_t *ssp = &(sp->s_sram);
39 dev_info_t *dip = sp->s_dip;
40 char name[MAXNAMELEN];
41
42 ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_UNINITIALIZED);
43
44 mutex_init(&(ssp->ss_lock), NULL, MUTEX_DRIVER, NULL);
45
46 /*
47 * Create a VMEM arena for the buffer table
48 * Note that these are not in the DDI/DKI.
49 * See "man rmalloc" for a possible alternative
50 */
51 (void) snprintf(name, MAXNAMELEN - 1, "%s%d_sram", ddi_driver_name(dip),
52 ddi_get_instance(dip));
53 ssp->ss_buf_tbl = vmem_create(name, (void *)1, EFX_BUF_TBL_SIZE, 1,
54 NULL, NULL, NULL, 1, VM_SLEEP | VMC_IDENTIFIER);
55
56 ssp->ss_state = SFXGE_SRAM_INITIALIZED;
57 }
58
59 int
60 sfxge_sram_buf_tbl_alloc(sfxge_t *sp, size_t n, uint32_t *idp)
61 {
62 sfxge_sram_t *ssp = &(sp->s_sram);
63 void *base;
64 int rc;
65
66 mutex_enter(&(ssp->ss_lock));
67
68 ASSERT(ssp->ss_state != SFXGE_SRAM_UNINITIALIZED);
69
70 if ((base = vmem_alloc(ssp->ss_buf_tbl, n, VM_NOSLEEP)) == NULL) {
71 rc = ENOSPC;
72 goto fail1;
73 }
74
75 *idp = (uint32_t)((uintptr_t)base - 1);
76
77 mutex_exit(&(ssp->ss_lock));
78
79 return (0);
80
81 fail1:
82 DTRACE_PROBE1(fail1, int, rc);
83
84 mutex_exit(&(ssp->ss_lock));
85
86 return (rc);
87 }
88
89 int
90 sfxge_sram_start(sfxge_t *sp)
91 {
92 sfxge_sram_t *ssp = &(sp->s_sram);
93
94 mutex_enter(&(ssp->ss_lock));
95
96 ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_INITIALIZED);
97 ASSERT3U(ssp->ss_count, ==, 0);
98
99 ssp->ss_state = SFXGE_SRAM_STARTED;
100
101 mutex_exit(&(ssp->ss_lock));
102
103 return (0);
104 }
105
106 int
107 sfxge_sram_buf_tbl_set(sfxge_t *sp, uint32_t id, efsys_mem_t *esmp,
108 size_t n)
109 {
110 sfxge_sram_t *ssp = &(sp->s_sram);
111 int rc;
112
113 mutex_enter(&(ssp->ss_lock));
114
115 ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
116
117 if ((rc = efx_sram_buf_tbl_set(sp->s_enp, id, esmp, n)) != 0)
118 goto fail1;
119
120 ssp->ss_count += n;
121
122 mutex_exit(&(ssp->ss_lock));
123
124 return (0);
125
126 fail1:
127 DTRACE_PROBE1(fail1, int, rc);
128
129 mutex_exit(&(ssp->ss_lock));
130
131 return (rc);
132 }
133
134 void
135 sfxge_sram_buf_tbl_clear(sfxge_t *sp, uint32_t id, size_t n)
136 {
137 sfxge_sram_t *ssp = &(sp->s_sram);
138
139 mutex_enter(&(ssp->ss_lock));
140
141 ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
142
143 ASSERT3U(ssp->ss_count, >=, n);
144 ssp->ss_count -= n;
145
146 efx_sram_buf_tbl_clear(sp->s_enp, id, n);
147
148 mutex_exit(&(ssp->ss_lock));
149 }
150
151 void
152 sfxge_sram_stop(sfxge_t *sp)
153 {
154 sfxge_sram_t *ssp = &(sp->s_sram);
155
156 mutex_enter(&(ssp->ss_lock));
157
158 ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_STARTED);
159 ASSERT3U(ssp->ss_count, ==, 0);
160
161 ssp->ss_state = SFXGE_SRAM_INITIALIZED;
162
163 mutex_exit(&(ssp->ss_lock));
164 }
165
166 void
167 sfxge_sram_buf_tbl_free(sfxge_t *sp, uint32_t id, size_t n)
168 {
169 sfxge_sram_t *ssp = &(sp->s_sram);
170 void *base;
171
172 mutex_enter(&(ssp->ss_lock));
173
174 ASSERT(ssp->ss_state != SFXGE_SRAM_UNINITIALIZED);
175
176 base = (void *)((uintptr_t)id + 1);
177 vmem_free(ssp->ss_buf_tbl, base, n);
178
179 mutex_exit(&(ssp->ss_lock));
180 }
181
182 static int
183 sfxge_sram_test(sfxge_t *sp, efx_pattern_type_t type)
184 {
185 sfxge_sram_t *ssp = &(sp->s_sram);
186 int rc;
187
188 if (ssp->ss_state != SFXGE_SRAM_INITIALIZED) {
189 rc = EFAULT;
190 goto fail1;
191 }
192
193 if (type >= EFX_PATTERN_NTYPES) {
194 rc = EINVAL;
195 goto fail2;
196 }
197
198 mutex_enter(&(ssp->ss_lock));
199
200 if ((rc = efx_sram_test(sp->s_enp, type)) != 0)
201 goto fail3;
202
203 mutex_exit(&(ssp->ss_lock));
204
205 return (0);
206
207 fail3:
208 DTRACE_PROBE(fail3);
209 mutex_exit(&(ssp->ss_lock));
210 fail2:
211 DTRACE_PROBE(fail2);
212 fail1:
213 DTRACE_PROBE1(fail1, int, rc);
214
215 return (rc);
216 }
217
218 int
219 sfxge_sram_ioctl(sfxge_t *sp, sfxge_sram_ioc_t *ssip)
220 {
221 int rc;
222
223 switch (ssip->ssi_op) {
224 case SFXGE_SRAM_OP_TEST: {
225 efx_pattern_type_t type = ssip->ssi_data;
226
227 if ((rc = sfxge_sram_test(sp, type)) != 0)
228 goto fail1;
229
230 break;
231 }
232 default:
233 rc = ENOTSUP;
234 goto fail1;
235 }
236
237 return (0);
238
239 fail1:
240 DTRACE_PROBE1(fail1, int, rc);
241
242 return (rc);
243 }
244
245 void
246 sfxge_sram_fini(sfxge_t *sp)
247 {
248 sfxge_sram_t *ssp = &(sp->s_sram);
249
250 ASSERT3U(ssp->ss_state, ==, SFXGE_SRAM_INITIALIZED);
251
252 /* Destroy the VMEM arena */
253 vmem_destroy(ssp->ss_buf_tbl);
254 ssp->ss_buf_tbl = NULL;
255
256 mutex_destroy(&(ssp->ss_lock));
257
258 ssp->ss_state = SFXGE_SRAM_UNINITIALIZED;
259 }