efx_nvram.c revision 227569
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
36static 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
54static 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
71efx_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
105fail1:
106	EFSYS_PROBE1(fail1, int, rc);
107
108	return (rc);
109}
110
111#if EFSYS_OPT_DIAG
112
113	__checkReturn		int
114efx_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
128fail1:
129	EFSYS_PROBE1(fail1, int, rc);
130
131	return (rc);
132}
133
134#endif	/* EFSYS_OPT_DIAG */
135
136	__checkReturn		int
137efx_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
155fail1:
156	EFSYS_PROBE1(fail1, int, rc);
157
158	return (rc);
159}
160
161	__checkReturn		int
162efx_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
182fail1:
183	EFSYS_PROBE1(fail1, int, rc);
184
185	return (rc);
186}
187
188	__checkReturn		int
189efx_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
212fail1:
213	EFSYS_PROBE1(fail1, int, rc);
214
215	return (rc);
216}
217
218	__checkReturn		int
219efx_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
242fail1:
243	EFSYS_PROBE1(fail1, int, rc);
244
245	return (rc);
246}
247
248	__checkReturn		int
249efx_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
269fail1:
270	EFSYS_PROBE1(fail1, int, rc);
271
272	return (rc);
273}
274
275	__checkReturn		int
276efx_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
299fail1:
300	EFSYS_PROBE1(fail1, int, rc);
301
302	return (rc);
303}
304
305				void
306efx_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
326efx_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
352fail1:
353	EFSYS_PROBE1(fail1, int, rc);
354
355	return (rc);
356}
357
358void
359efx_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