xref: /freebsd/sys/dev/sfxge/common/efx_nvram.c (revision 10b59a9b4add0320d52c15ce057dd697261e7dfc)
1 /*-
2  * Copyright 2009 Solarflare Communications Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS AND
14  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23  * SUCH DAMAGE.
24  */
25 
26 #include "efsys.h"
27 #include "efx.h"
28 #include "efx_types.h"
29 #include "efx_regs.h"
30 #include "efx_impl.h"
31 
32 #if EFSYS_OPT_NVRAM
33 
34 #if EFSYS_OPT_FALCON
35 
36 static efx_nvram_ops_t	__cs	__efx_nvram_falcon_ops = {
37 #if EFSYS_OPT_DIAG
38 	falcon_nvram_test,		/* envo_test */
39 #endif	/* EFSYS_OPT_DIAG */
40 	falcon_nvram_size,		/* envo_size */
41 	falcon_nvram_get_version,	/* envo_get_version */
42 	falcon_nvram_rw_start,		/* envo_rw_start */
43 	falcon_nvram_read_chunk,	/* envo_read_chunk */
44 	falcon_nvram_erase,		/* envo_erase */
45 	falcon_nvram_write_chunk,	/* envo_write_chunk */
46 	falcon_nvram_rw_finish,		/* envo_rw_finish */
47 	falcon_nvram_set_version,	/* envo_set_version */
48 };
49 
50 #endif	/* EFSYS_OPT_FALCON */
51 
52 #if EFSYS_OPT_SIENA
53 
54 static efx_nvram_ops_t	__cs	__efx_nvram_siena_ops = {
55 #if EFSYS_OPT_DIAG
56 	siena_nvram_test,		/* envo_test */
57 #endif	/* EFSYS_OPT_DIAG */
58 	siena_nvram_size,		/* envo_size */
59 	siena_nvram_get_version,	/* envo_get_version */
60 	siena_nvram_rw_start,		/* envo_rw_start */
61 	siena_nvram_read_chunk,		/* envo_read_chunk */
62 	siena_nvram_erase,		/* envo_erase */
63 	siena_nvram_write_chunk,	/* envo_write_chunk */
64 	siena_nvram_rw_finish,		/* envo_rw_finish */
65 	siena_nvram_set_version,	/* envo_set_version */
66 };
67 
68 #endif	/* EFSYS_OPT_SIENA */
69 
70 	__checkReturn	int
71 efx_nvram_init(
72 	__in		efx_nic_t *enp)
73 {
74 	efx_nvram_ops_t *envop;
75 	int rc;
76 
77 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
78 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
79 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
80 
81 	switch (enp->en_family) {
82 #if EFSYS_OPT_FALCON
83 	case EFX_FAMILY_FALCON:
84 		envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops;
85 		break;
86 #endif	/* EFSYS_OPT_FALCON */
87 
88 #if EFSYS_OPT_SIENA
89 	case EFX_FAMILY_SIENA:
90 		envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops;
91 		break;
92 #endif	/* EFSYS_OPT_SIENA */
93 
94 	default:
95 		EFSYS_ASSERT(0);
96 		rc = ENOTSUP;
97 		goto fail1;
98 	}
99 
100 	enp->en_envop = envop;
101 	enp->en_mod_flags |= EFX_MOD_NVRAM;
102 
103 	return (0);
104 
105 fail1:
106 	EFSYS_PROBE1(fail1, int, rc);
107 
108 	return (rc);
109 }
110 
111 #if EFSYS_OPT_DIAG
112 
113 	__checkReturn		int
114 efx_nvram_test(
115 	__in			efx_nic_t *enp)
116 {
117 	efx_nvram_ops_t *envop = enp->en_envop;
118 	int rc;
119 
120 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
121 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
122 
123 	if ((rc = envop->envo_test(enp)) != 0)
124 		goto fail1;
125 
126 	return (0);
127 
128 fail1:
129 	EFSYS_PROBE1(fail1, int, rc);
130 
131 	return (rc);
132 }
133 
134 #endif	/* EFSYS_OPT_DIAG */
135 
136 	__checkReturn		int
137 efx_nvram_size(
138 	__in			efx_nic_t *enp,
139 	__in			efx_nvram_type_t type,
140 	__out			size_t *sizep)
141 {
142 	efx_nvram_ops_t *envop = enp->en_envop;
143 	int rc;
144 
145 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
146 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
147 
148 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
149 
150 	if ((rc = envop->envo_size(enp, type, sizep)) != 0)
151 		goto fail1;
152 
153 	return (0);
154 
155 fail1:
156 	EFSYS_PROBE1(fail1, int, rc);
157 
158 	return (rc);
159 }
160 
161 	__checkReturn		int
162 efx_nvram_get_version(
163 	__in			efx_nic_t *enp,
164 	__in			efx_nvram_type_t type,
165 	__out			uint32_t *subtypep,
166 	__out_ecount(4)		uint16_t version[4])
167 {
168 	efx_nvram_ops_t *envop = enp->en_envop;
169 	int rc;
170 
171 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
172 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
173 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
174 
175 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
176 
177 	if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0)
178 		goto fail1;
179 
180 	return (0);
181 
182 fail1:
183 	EFSYS_PROBE1(fail1, int, rc);
184 
185 	return (rc);
186 }
187 
188 	__checkReturn		int
189 efx_nvram_rw_start(
190 	__in			efx_nic_t *enp,
191 	__in			efx_nvram_type_t type,
192 	__out_opt		size_t *chunk_sizep)
193 {
194 	efx_nvram_ops_t *envop = enp->en_envop;
195 	int rc;
196 
197 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
198 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
199 
200 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
201 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
202 
203 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
204 
205 	if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0)
206 		goto fail1;
207 
208 	enp->en_nvram_locked = type;
209 
210 	return (0);
211 
212 fail1:
213 	EFSYS_PROBE1(fail1, int, rc);
214 
215 	return (rc);
216 }
217 
218 	__checkReturn		int
219 efx_nvram_read_chunk(
220 	__in			efx_nic_t *enp,
221 	__in			efx_nvram_type_t type,
222 	__in			unsigned int offset,
223 	__out_bcount(size)	caddr_t data,
224 	__in			size_t size)
225 {
226 	efx_nvram_ops_t *envop = enp->en_envop;
227 	int rc;
228 
229 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
230 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
231 
232 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
233 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
234 
235 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
236 
237 	if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0)
238 		goto fail1;
239 
240 	return (0);
241 
242 fail1:
243 	EFSYS_PROBE1(fail1, int, rc);
244 
245 	return (rc);
246 }
247 
248 	__checkReturn		int
249 efx_nvram_erase(
250 	__in			efx_nic_t *enp,
251 	__in			efx_nvram_type_t type)
252 {
253 	efx_nvram_ops_t *envop = enp->en_envop;
254 	int rc;
255 
256 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
257 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
258 
259 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
260 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
261 
262 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
263 
264 	if ((rc = envop->envo_erase(enp, type)) != 0)
265 		goto fail1;
266 
267 	return (0);
268 
269 fail1:
270 	EFSYS_PROBE1(fail1, int, rc);
271 
272 	return (rc);
273 }
274 
275 	__checkReturn		int
276 efx_nvram_write_chunk(
277 	__in			efx_nic_t *enp,
278 	__in			efx_nvram_type_t type,
279 	__in			unsigned int offset,
280 	__in_bcount(size)	caddr_t data,
281 	__in			size_t size)
282 {
283 	efx_nvram_ops_t *envop = enp->en_envop;
284 	int rc;
285 
286 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
287 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
288 
289 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
290 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
291 
292 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
293 
294 	if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0)
295 		goto fail1;
296 
297 	return (0);
298 
299 fail1:
300 	EFSYS_PROBE1(fail1, int, rc);
301 
302 	return (rc);
303 }
304 
305 				void
306 efx_nvram_rw_finish(
307 	__in			efx_nic_t *enp,
308 	__in			efx_nvram_type_t type)
309 {
310 	efx_nvram_ops_t *envop = enp->en_envop;
311 
312 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
313 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
314 
315 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
316 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
317 
318 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
319 
320 	envop->envo_rw_finish(enp, type);
321 
322 	enp->en_nvram_locked = EFX_NVRAM_INVALID;
323 }
324 
325 	__checkReturn		int
326 efx_nvram_set_version(
327 	__in			efx_nic_t *enp,
328 	__in			efx_nvram_type_t type,
329 	__out			uint16_t version[4])
330 {
331 	efx_nvram_ops_t *envop = enp->en_envop;
332 	int rc;
333 
334 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
335 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
336 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
337 
338 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
339 
340 	/*
341 	 * The Siena implementation of envo_set_version() will attempt to
342 	 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
343 	 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
344 	 */
345 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
346 
347 	if ((rc = envop->envo_set_version(enp, type, version)) != 0)
348 		goto fail1;
349 
350 	return (0);
351 
352 fail1:
353 	EFSYS_PROBE1(fail1, int, rc);
354 
355 	return (rc);
356 }
357 
358 void
359 efx_nvram_fini(
360 	__in		efx_nic_t *enp)
361 {
362 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
363 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
364 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
365 
366 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
367 
368 	enp->en_envop = NULL;
369 	enp->en_mod_flags &= ~EFX_MOD_NVRAM;
370 }
371 
372 #endif	/* EFSYS_OPT_NVRAM */
373