xref: /freebsd/sys/dev/sfxge/common/efx_nvram.c (revision ba00ec3d539f213abbda3a45ef8c539306cac098)
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 <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
28 
29 #include "efsys.h"
30 #include "efx.h"
31 #include "efx_types.h"
32 #include "efx_regs.h"
33 #include "efx_impl.h"
34 
35 #if EFSYS_OPT_NVRAM
36 
37 #if EFSYS_OPT_FALCON
38 
39 static efx_nvram_ops_t	__cs	__efx_nvram_falcon_ops = {
40 #if EFSYS_OPT_DIAG
41 	falcon_nvram_test,		/* envo_test */
42 #endif	/* EFSYS_OPT_DIAG */
43 	falcon_nvram_size,		/* envo_size */
44 	falcon_nvram_get_version,	/* envo_get_version */
45 	falcon_nvram_rw_start,		/* envo_rw_start */
46 	falcon_nvram_read_chunk,	/* envo_read_chunk */
47 	falcon_nvram_erase,		/* envo_erase */
48 	falcon_nvram_write_chunk,	/* envo_write_chunk */
49 	falcon_nvram_rw_finish,		/* envo_rw_finish */
50 	falcon_nvram_set_version,	/* envo_set_version */
51 };
52 
53 #endif	/* EFSYS_OPT_FALCON */
54 
55 #if EFSYS_OPT_SIENA
56 
57 static efx_nvram_ops_t	__cs	__efx_nvram_siena_ops = {
58 #if EFSYS_OPT_DIAG
59 	siena_nvram_test,		/* envo_test */
60 #endif	/* EFSYS_OPT_DIAG */
61 	siena_nvram_size,		/* envo_size */
62 	siena_nvram_get_version,	/* envo_get_version */
63 	siena_nvram_rw_start,		/* envo_rw_start */
64 	siena_nvram_read_chunk,		/* envo_read_chunk */
65 	siena_nvram_erase,		/* envo_erase */
66 	siena_nvram_write_chunk,	/* envo_write_chunk */
67 	siena_nvram_rw_finish,		/* envo_rw_finish */
68 	siena_nvram_set_version,	/* envo_set_version */
69 };
70 
71 #endif	/* EFSYS_OPT_SIENA */
72 
73 	__checkReturn	int
74 efx_nvram_init(
75 	__in		efx_nic_t *enp)
76 {
77 	efx_nvram_ops_t *envop;
78 	int rc;
79 
80 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
81 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
82 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NVRAM));
83 
84 	switch (enp->en_family) {
85 #if EFSYS_OPT_FALCON
86 	case EFX_FAMILY_FALCON:
87 		envop = (efx_nvram_ops_t *)&__efx_nvram_falcon_ops;
88 		break;
89 #endif	/* EFSYS_OPT_FALCON */
90 
91 #if EFSYS_OPT_SIENA
92 	case EFX_FAMILY_SIENA:
93 		envop = (efx_nvram_ops_t *)&__efx_nvram_siena_ops;
94 		break;
95 #endif	/* EFSYS_OPT_SIENA */
96 
97 	default:
98 		EFSYS_ASSERT(0);
99 		rc = ENOTSUP;
100 		goto fail1;
101 	}
102 
103 	enp->en_envop = envop;
104 	enp->en_mod_flags |= EFX_MOD_NVRAM;
105 
106 	return (0);
107 
108 fail1:
109 	EFSYS_PROBE1(fail1, int, rc);
110 
111 	return (rc);
112 }
113 
114 #if EFSYS_OPT_DIAG
115 
116 	__checkReturn		int
117 efx_nvram_test(
118 	__in			efx_nic_t *enp)
119 {
120 	efx_nvram_ops_t *envop = enp->en_envop;
121 	int rc;
122 
123 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
124 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
125 
126 	if ((rc = envop->envo_test(enp)) != 0)
127 		goto fail1;
128 
129 	return (0);
130 
131 fail1:
132 	EFSYS_PROBE1(fail1, int, rc);
133 
134 	return (rc);
135 }
136 
137 #endif	/* EFSYS_OPT_DIAG */
138 
139 	__checkReturn		int
140 efx_nvram_size(
141 	__in			efx_nic_t *enp,
142 	__in			efx_nvram_type_t type,
143 	__out			size_t *sizep)
144 {
145 	efx_nvram_ops_t *envop = enp->en_envop;
146 	int rc;
147 
148 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
149 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
150 
151 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
152 
153 	if ((rc = envop->envo_size(enp, type, sizep)) != 0)
154 		goto fail1;
155 
156 	return (0);
157 
158 fail1:
159 	EFSYS_PROBE1(fail1, int, rc);
160 
161 	return (rc);
162 }
163 
164 	__checkReturn		int
165 efx_nvram_get_version(
166 	__in			efx_nic_t *enp,
167 	__in			efx_nvram_type_t type,
168 	__out			uint32_t *subtypep,
169 	__out_ecount(4)		uint16_t version[4])
170 {
171 	efx_nvram_ops_t *envop = enp->en_envop;
172 	int rc;
173 
174 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
175 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
176 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
177 
178 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
179 
180 	if ((rc = envop->envo_get_version(enp, type, subtypep, version)) != 0)
181 		goto fail1;
182 
183 	return (0);
184 
185 fail1:
186 	EFSYS_PROBE1(fail1, int, rc);
187 
188 	return (rc);
189 }
190 
191 	__checkReturn		int
192 efx_nvram_rw_start(
193 	__in			efx_nic_t *enp,
194 	__in			efx_nvram_type_t type,
195 	__out_opt		size_t *chunk_sizep)
196 {
197 	efx_nvram_ops_t *envop = enp->en_envop;
198 	int rc;
199 
200 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
201 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
202 
203 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
204 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
205 
206 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
207 
208 	if ((rc = envop->envo_rw_start(enp, type, chunk_sizep)) != 0)
209 		goto fail1;
210 
211 	enp->en_nvram_locked = type;
212 
213 	return (0);
214 
215 fail1:
216 	EFSYS_PROBE1(fail1, int, rc);
217 
218 	return (rc);
219 }
220 
221 	__checkReturn		int
222 efx_nvram_read_chunk(
223 	__in			efx_nic_t *enp,
224 	__in			efx_nvram_type_t type,
225 	__in			unsigned int offset,
226 	__out_bcount(size)	caddr_t data,
227 	__in			size_t size)
228 {
229 	efx_nvram_ops_t *envop = enp->en_envop;
230 	int rc;
231 
232 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
233 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
234 
235 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
236 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
237 
238 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
239 
240 	if ((rc = envop->envo_read_chunk(enp, type, offset, data, size)) != 0)
241 		goto fail1;
242 
243 	return (0);
244 
245 fail1:
246 	EFSYS_PROBE1(fail1, int, rc);
247 
248 	return (rc);
249 }
250 
251 	__checkReturn		int
252 efx_nvram_erase(
253 	__in			efx_nic_t *enp,
254 	__in			efx_nvram_type_t type)
255 {
256 	efx_nvram_ops_t *envop = enp->en_envop;
257 	int rc;
258 
259 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
260 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
261 
262 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
263 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
264 
265 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
266 
267 	if ((rc = envop->envo_erase(enp, type)) != 0)
268 		goto fail1;
269 
270 	return (0);
271 
272 fail1:
273 	EFSYS_PROBE1(fail1, int, rc);
274 
275 	return (rc);
276 }
277 
278 	__checkReturn		int
279 efx_nvram_write_chunk(
280 	__in			efx_nic_t *enp,
281 	__in			efx_nvram_type_t type,
282 	__in			unsigned int offset,
283 	__in_bcount(size)	caddr_t data,
284 	__in			size_t size)
285 {
286 	efx_nvram_ops_t *envop = enp->en_envop;
287 	int rc;
288 
289 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
290 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
291 
292 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
293 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
294 
295 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
296 
297 	if ((rc = envop->envo_write_chunk(enp, type, offset, data, size)) != 0)
298 		goto fail1;
299 
300 	return (0);
301 
302 fail1:
303 	EFSYS_PROBE1(fail1, int, rc);
304 
305 	return (rc);
306 }
307 
308 				void
309 efx_nvram_rw_finish(
310 	__in			efx_nic_t *enp,
311 	__in			efx_nvram_type_t type)
312 {
313 	efx_nvram_ops_t *envop = enp->en_envop;
314 
315 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
316 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
317 
318 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
319 	EFSYS_ASSERT3U(type, !=, EFX_NVRAM_INVALID);
320 
321 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, type);
322 
323 	envop->envo_rw_finish(enp, type);
324 
325 	enp->en_nvram_locked = EFX_NVRAM_INVALID;
326 }
327 
328 	__checkReturn		int
329 efx_nvram_set_version(
330 	__in			efx_nic_t *enp,
331 	__in			efx_nvram_type_t type,
332 	__out			uint16_t version[4])
333 {
334 	efx_nvram_ops_t *envop = enp->en_envop;
335 	int rc;
336 
337 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
338 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
339 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
340 
341 	EFSYS_ASSERT3U(type, <, EFX_NVRAM_NTYPES);
342 
343 	/*
344 	 * The Siena implementation of envo_set_version() will attempt to
345 	 * acquire the NVRAM_UPDATE lock for the DYNAMIC_CONFIG sector.
346 	 * Therefore, you can't have already acquired the NVRAM_UPDATE lock.
347 	 */
348 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
349 
350 	if ((rc = envop->envo_set_version(enp, type, version)) != 0)
351 		goto fail1;
352 
353 	return (0);
354 
355 fail1:
356 	EFSYS_PROBE1(fail1, int, rc);
357 
358 	return (rc);
359 }
360 
361 void
362 efx_nvram_fini(
363 	__in		efx_nic_t *enp)
364 {
365 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
366 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
367 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NVRAM);
368 
369 	EFSYS_ASSERT3U(enp->en_nvram_locked, ==, EFX_NVRAM_INVALID);
370 
371 	enp->en_envop = NULL;
372 	enp->en_mod_flags &= ~EFX_MOD_NVRAM;
373 }
374 
375 #endif	/* EFSYS_OPT_NVRAM */
376