xref: /freebsd/sys/dev/sfxge/common/efx_nic.c (revision 788ca347b816afd83b2885e0c79aeeb88649b2ab)
1 /*-
2  * Copyright 2007-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 	__checkReturn	int
36 efx_family(
37 	__in		uint16_t venid,
38 	__in		uint16_t devid,
39 	__out		efx_family_t *efp)
40 {
41 #if EFSYS_OPT_FALCON
42 	if (venid == EFX_PCI_VENID_SFC && devid == EFX_PCI_DEVID_FALCON) {
43 		*efp = EFX_FAMILY_FALCON;
44 		return (0);
45 	}
46 #endif
47 #if EFSYS_OPT_SIENA
48 	if (venid == EFX_PCI_VENID_SFC && devid == EFX_PCI_DEVID_BETHPAGE) {
49 		*efp = EFX_FAMILY_SIENA;
50 		return (0);
51 	}
52 	if (venid == EFX_PCI_VENID_SFC && devid == EFX_PCI_DEVID_SIENA) {
53 		*efp = EFX_FAMILY_SIENA;
54 		return (0);
55 	}
56 	if (venid == EFX_PCI_VENID_SFC &&
57 	    devid == EFX_PCI_DEVID_SIENA_F1_UNINIT) {
58 		*efp = EFX_FAMILY_SIENA;
59 		return (0);
60 	}
61 #endif
62 	return (ENOTSUP);
63 }
64 
65 /*
66  * To support clients which aren't provided with any PCI context infer
67  * the hardware family by inspecting the hardware. Obviously the caller
68  * must be damn sure they're really talking to a supported device.
69  */
70 	__checkReturn	int
71 efx_infer_family(
72 	__in		efsys_bar_t *esbp,
73 	__out		efx_family_t *efp)
74 {
75 	efx_family_t family;
76 	efx_oword_t oword;
77 	unsigned int portnum;
78 	int rc;
79 
80 	EFSYS_BAR_READO(esbp, FR_AZ_CS_DEBUG_REG_OFST, &oword, B_TRUE);
81 	portnum = EFX_OWORD_FIELD(oword, FRF_CZ_CS_PORT_NUM);
82 	switch (portnum) {
83 #if EFSYS_OPT_FALCON
84 	case 0:
85 		family = EFX_FAMILY_FALCON;
86 		break;
87 #endif
88 #if EFSYS_OPT_SIENA
89 	case 1:
90 	case 2:
91 		family = EFX_FAMILY_SIENA;
92 		break;
93 #endif
94 	default:
95 		rc = ENOTSUP;
96 		goto fail1;
97 	}
98 
99 	if (efp != NULL)
100 		*efp = family;
101 	return (0);
102 
103 fail1:
104 	EFSYS_PROBE1(fail1, int, rc);
105 
106 	return (rc);
107 }
108 
109 /*
110  * The built-in default value device id for port 1 of Siena is 0x0810.
111  * manftest needs to be able to cope with that.
112  */
113 
114 #define	EFX_BIU_MAGIC0	0x01234567
115 #define	EFX_BIU_MAGIC1	0xfedcba98
116 
117 static	__checkReturn	int
118 efx_nic_biu_test(
119 	__in		efx_nic_t *enp)
120 {
121 	efx_oword_t oword;
122 	int rc;
123 
124 	/*
125 	 * Write magic values to scratch registers 0 and 1, then
126 	 * verify that the values were written correctly.  Interleave
127 	 * the accesses to ensure that the BIU is not just reading
128 	 * back the cached value that was last written.
129 	 */
130 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0);
131 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword);
132 
133 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1);
134 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword);
135 
136 	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword);
137 	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) {
138 		rc = EIO;
139 		goto fail1;
140 	}
141 
142 	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword);
143 	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) {
144 		rc = EIO;
145 		goto fail2;
146 	}
147 
148 	/*
149 	 * Perform the same test, with the values swapped.  This
150 	 * ensures that subsequent tests don't start with the correct
151 	 * values already written into the scratch registers.
152 	 */
153 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC1);
154 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 0, &oword);
155 
156 	EFX_POPULATE_OWORD_1(oword, FRF_AZ_DRIVER_DW0, EFX_BIU_MAGIC0);
157 	EFX_BAR_TBL_WRITEO(enp, FR_AZ_DRIVER_REG, 1, &oword);
158 
159 	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 0, &oword);
160 	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC1) {
161 		rc = EIO;
162 		goto fail3;
163 	}
164 
165 	EFX_BAR_TBL_READO(enp, FR_AZ_DRIVER_REG, 1, &oword);
166 	if (EFX_OWORD_FIELD(oword, FRF_AZ_DRIVER_DW0) != EFX_BIU_MAGIC0) {
167 		rc = EIO;
168 		goto fail4;
169 	}
170 
171 	return (0);
172 
173 fail4:
174 	EFSYS_PROBE(fail4);
175 fail3:
176 	EFSYS_PROBE(fail3);
177 fail2:
178 	EFSYS_PROBE(fail2);
179 fail1:
180 	EFSYS_PROBE1(fail1, int, rc);
181 
182 	return (rc);
183 }
184 
185 #if EFSYS_OPT_FALCON
186 
187 static efx_nic_ops_t	__cs __efx_nic_falcon_ops = {
188 	falcon_nic_probe,		/* eno_probe */
189 	falcon_nic_reset,		/* eno_reset */
190 	falcon_nic_init,		/* eno_init */
191 #if EFSYS_OPT_DIAG
192 	falcon_sram_test,		/* eno_sram_test */
193 	falcon_nic_register_test,	/* eno_register_test */
194 #endif	/* EFSYS_OPT_DIAG */
195 	falcon_nic_fini,		/* eno_fini */
196 	falcon_nic_unprobe,		/* eno_unprobe */
197 };
198 
199 #endif	/* EFSYS_OPT_FALCON */
200 
201 #if EFSYS_OPT_SIENA
202 
203 static efx_nic_ops_t	__cs __efx_nic_siena_ops = {
204 	siena_nic_probe,		/* eno_probe */
205 	siena_nic_reset,		/* eno_reset */
206 	siena_nic_init,			/* eno_init */
207 #if EFSYS_OPT_DIAG
208 	siena_sram_test,		/* eno_sram_test */
209 	siena_nic_register_test,	/* eno_register_test */
210 #endif	/* EFSYS_OPT_DIAG */
211 	siena_nic_fini,			/* eno_fini */
212 	siena_nic_unprobe,		/* eno_unprobe */
213 };
214 
215 #endif	/* EFSYS_OPT_SIENA */
216 
217 	__checkReturn	int
218 efx_nic_create(
219 	__in		efx_family_t family,
220 	__in		efsys_identifier_t *esip,
221 	__in		efsys_bar_t *esbp,
222 	__in		efsys_lock_t *eslp,
223 	__deref_out	efx_nic_t **enpp)
224 {
225 	efx_nic_t *enp;
226 	int rc;
227 
228 	EFSYS_ASSERT3U(family, >, EFX_FAMILY_INVALID);
229 	EFSYS_ASSERT3U(family, <, EFX_FAMILY_NTYPES);
230 
231 	/* Allocate a NIC object */
232 	EFSYS_KMEM_ALLOC(esip, sizeof (efx_nic_t), enp);
233 
234 	if (enp == NULL) {
235 		rc = ENOMEM;
236 		goto fail1;
237 	}
238 
239 	enp->en_magic = EFX_NIC_MAGIC;
240 
241 	switch (family) {
242 #if EFSYS_OPT_FALCON
243 	case EFX_FAMILY_FALCON:
244 		enp->en_enop = (efx_nic_ops_t *)&__efx_nic_falcon_ops;
245 		enp->en_features = 0;
246 		break;
247 #endif	/* EFSYS_OPT_FALCON */
248 
249 #if EFSYS_OPT_SIENA
250 	case EFX_FAMILY_SIENA:
251 		enp->en_enop = (efx_nic_ops_t *)&__efx_nic_siena_ops;
252 		enp->en_features =
253 		    EFX_FEATURE_IPV6 |
254 		    EFX_FEATURE_LFSR_HASH_INSERT |
255 		    EFX_FEATURE_LINK_EVENTS |
256 		    EFX_FEATURE_PERIODIC_MAC_STATS |
257 		    EFX_FEATURE_WOL |
258 		    EFX_FEATURE_MCDI |
259 		    EFX_FEATURE_LOOKAHEAD_SPLIT |
260 		    EFX_FEATURE_MAC_HEADER_FILTERS;
261 		break;
262 #endif	/* EFSYS_OPT_SIENA */
263 
264 	default:
265 		rc = ENOTSUP;
266 		goto fail2;
267 	}
268 
269 	enp->en_family = family;
270 	enp->en_esip = esip;
271 	enp->en_esbp = esbp;
272 	enp->en_eslp = eslp;
273 
274 	*enpp = enp;
275 
276 	return (0);
277 
278 fail2:
279 	EFSYS_PROBE(fail3);
280 
281 	enp->en_magic = 0;
282 
283 	/* Free the NIC object */
284 	EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
285 
286 fail1:
287 	EFSYS_PROBE1(fail1, int, rc);
288 
289 	return (rc);
290 }
291 
292 	__checkReturn	int
293 efx_nic_probe(
294 	__in		efx_nic_t *enp)
295 {
296 	efx_nic_ops_t *enop;
297 	efx_oword_t oword;
298 	int rc;
299 
300 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
301 #if EFSYS_OPT_MCDI
302 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
303 #endif	/* EFSYS_OPT_MCDI */
304 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_PROBE));
305 
306 	/* Test BIU */
307 	if ((rc = efx_nic_biu_test(enp)) != 0)
308 		goto fail1;
309 
310 	/* Clear the region register */
311 	EFX_POPULATE_OWORD_4(oword,
312 	    FRF_AZ_ADR_REGION0, 0,
313 	    FRF_AZ_ADR_REGION1, (1 << 16),
314 	    FRF_AZ_ADR_REGION2, (2 << 16),
315 	    FRF_AZ_ADR_REGION3, (3 << 16));
316 	EFX_BAR_WRITEO(enp, FR_AZ_ADR_REGION_REG, &oword);
317 
318 	enop = enp->en_enop;
319 	if ((rc = enop->eno_probe(enp)) != 0)
320 		goto fail2;
321 
322 	if ((rc = efx_phy_probe(enp)) != 0)
323 		goto fail3;
324 
325 	enp->en_mod_flags |= EFX_MOD_PROBE;
326 
327 	return (0);
328 
329 fail3:
330 	EFSYS_PROBE(fail3);
331 
332 	enop->eno_unprobe(enp);
333 
334 fail2:
335 	EFSYS_PROBE(fail2);
336 fail1:
337 	EFSYS_PROBE1(fail1, int, rc);
338 
339 	return (rc);
340 }
341 
342 #if EFSYS_OPT_PCIE_TUNE
343 
344 	__checkReturn	int
345 efx_nic_pcie_tune(
346 	__in		efx_nic_t *enp,
347 	unsigned int	nlanes)
348 {
349 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
350 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
351 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
352 
353 #if EFSYS_OPT_FALCON
354 	if (enp->en_family == EFX_FAMILY_FALCON)
355 		return (falcon_nic_pcie_tune(enp, nlanes));
356 #endif
357 	return (ENOTSUP);
358 }
359 
360 	__checkReturn	int
361 efx_nic_pcie_extended_sync(
362 	__in		efx_nic_t *enp)
363 {
364 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
365 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
366 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
367 
368 #if EFSYS_OPT_SIENA
369 	if (enp->en_family == EFX_FAMILY_SIENA)
370 		return (siena_nic_pcie_extended_sync(enp));
371 #endif
372 
373 	return (ENOTSUP);
374 }
375 
376 #endif	/* EFSYS_OPT_PCIE_TUNE */
377 
378 	__checkReturn	int
379 efx_nic_init(
380 	__in		efx_nic_t *enp)
381 {
382 	efx_nic_ops_t *enop = enp->en_enop;
383 	int rc;
384 
385 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
386 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
387 
388 	if (enp->en_mod_flags & EFX_MOD_NIC) {
389 		rc = EINVAL;
390 		goto fail1;
391 	}
392 
393 	if ((rc = enop->eno_init(enp)) != 0)
394 		goto fail2;
395 
396 	enp->en_mod_flags |= EFX_MOD_NIC;
397 
398 	return (0);
399 
400 fail2:
401 	EFSYS_PROBE(fail2);
402 fail1:
403 	EFSYS_PROBE1(fail1, int, rc);
404 
405 	return (rc);
406 }
407 
408 			void
409 efx_nic_fini(
410 	__in		efx_nic_t *enp)
411 {
412 	efx_nic_ops_t *enop = enp->en_enop;
413 
414 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
415 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
416 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_NIC);
417 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
418 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
419 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
420 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
421 
422 	enop->eno_fini(enp);
423 
424 	enp->en_mod_flags &= ~EFX_MOD_NIC;
425 }
426 
427 			void
428 efx_nic_unprobe(
429 	__in		efx_nic_t *enp)
430 {
431 	efx_nic_ops_t *enop = enp->en_enop;
432 
433 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
434 #if EFSYS_OPT_MCDI
435 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_MCDI);
436 #endif	/* EFSYS_OPT_MCDI */
437 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
438 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
439 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_INTR));
440 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
441 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_RX));
442 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TX));
443 
444 	efx_phy_unprobe(enp);
445 
446 	enop->eno_unprobe(enp);
447 
448 	enp->en_mod_flags &= ~EFX_MOD_PROBE;
449 }
450 
451 			void
452 efx_nic_destroy(
453 	__in	efx_nic_t *enp)
454 {
455 	efsys_identifier_t *esip = enp->en_esip;
456 
457 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
458 	EFSYS_ASSERT3U(enp->en_mod_flags, ==, 0);
459 
460 	enp->en_family = 0;
461 	enp->en_esip = NULL;
462 	enp->en_esbp = NULL;
463 	enp->en_eslp = NULL;
464 
465 	enp->en_enop = NULL;
466 
467 	enp->en_magic = 0;
468 
469 	/* Free the NIC object */
470 	EFSYS_KMEM_FREE(esip, sizeof (efx_nic_t), enp);
471 }
472 
473 	__checkReturn	int
474 efx_nic_reset(
475 	__in		efx_nic_t *enp)
476 {
477 	efx_nic_ops_t *enop = enp->en_enop;
478 	unsigned int mod_flags;
479 	int rc;
480 
481 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
482 	EFSYS_ASSERT(enp->en_mod_flags & EFX_MOD_PROBE);
483 	/*
484 	 * All modules except the MCDI, PROBE, NVRAM, VPD, MON (which we
485 	 * do not reset here) must have been shut down or never initialized.
486 	 *
487 	 * A rule of thumb here is: If the controller or MC reboots, is *any*
488 	 * state lost. If it's lost and needs reapplying, then the module
489 	 * *must* not be initialised during the reset.
490 	 */
491 	mod_flags = enp->en_mod_flags;
492 	mod_flags &= ~(EFX_MOD_MCDI | EFX_MOD_PROBE | EFX_MOD_NVRAM |
493 		    EFX_MOD_VPD | EFX_MOD_MON);
494 	EFSYS_ASSERT3U(mod_flags, ==, 0);
495 	if (mod_flags != 0) {
496 		rc = EINVAL;
497 		goto fail1;
498 	}
499 
500 	if ((rc = enop->eno_reset(enp)) != 0)
501 		goto fail2;
502 
503 	enp->en_reset_flags |= EFX_RESET_MAC;
504 
505 	return (0);
506 
507 fail2:
508 	EFSYS_PROBE(fail2);
509 fail1:
510 	EFSYS_PROBE1(fail1, int, rc);
511 
512 	return (rc);
513 }
514 
515 			const efx_nic_cfg_t *
516 efx_nic_cfg_get(
517 	__in		efx_nic_t *enp)
518 {
519 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
520 
521 	return (&(enp->en_nic_cfg));
522 }
523 
524 #if EFSYS_OPT_DIAG
525 
526 	__checkReturn	int
527 efx_nic_register_test(
528 	__in		efx_nic_t *enp)
529 {
530 	efx_nic_ops_t *enop = enp->en_enop;
531 	int rc;
532 
533 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
534 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
535 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_NIC));
536 
537 	if ((rc = enop->eno_register_test(enp)) != 0)
538 		goto fail1;
539 
540 	return (0);
541 
542 fail1:
543 	EFSYS_PROBE1(fail1, int, rc);
544 
545 	return (rc);
546 }
547 
548 	__checkReturn	int
549 efx_nic_test_registers(
550 	__in		efx_nic_t *enp,
551 	__in		efx_register_set_t *rsp,
552 	__in		size_t count)
553 {
554 	unsigned int bit;
555 	efx_oword_t original;
556 	efx_oword_t reg;
557 	efx_oword_t buf;
558 	int rc;
559 
560 	while (count > 0) {
561 		/* This function is only suitable for registers */
562 		EFSYS_ASSERT(rsp->rows == 1);
563 
564 		/* bit sweep on and off */
565 		EFSYS_BAR_READO(enp->en_esbp, rsp->address, &original,
566 			    B_TRUE);
567 		for (bit = 0; bit < 128; bit++) {
568 			/* Is this bit in the mask? */
569 			if (~(rsp->mask.eo_u32[bit >> 5]) & (1 << bit))
570 				continue;
571 
572 			/* Test this bit can be set in isolation */
573 			reg = original;
574 			EFX_AND_OWORD(reg, rsp->mask);
575 			EFX_SET_OWORD_BIT(reg, bit);
576 
577 			EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &reg,
578 				    B_TRUE);
579 			EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
580 				    B_TRUE);
581 
582 			EFX_AND_OWORD(buf, rsp->mask);
583 			if (memcmp(&reg, &buf, sizeof (reg))) {
584 				rc = EIO;
585 				goto fail1;
586 			}
587 
588 			/* Test this bit can be cleared in isolation */
589 			EFX_OR_OWORD(reg, rsp->mask);
590 			EFX_CLEAR_OWORD_BIT(reg, bit);
591 
592 			EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &reg,
593 				    B_TRUE);
594 			EFSYS_BAR_READO(enp->en_esbp, rsp->address, &buf,
595 				    B_TRUE);
596 
597 			EFX_AND_OWORD(buf, rsp->mask);
598 			if (memcmp(&reg, &buf, sizeof (reg))) {
599 				rc = EIO;
600 				goto fail2;
601 			}
602 		}
603 
604 		/* Restore the old value */
605 		EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original,
606 			    B_TRUE);
607 
608 		--count;
609 		++rsp;
610 	}
611 
612 	return (0);
613 
614 fail2:
615 	EFSYS_PROBE(fail2);
616 fail1:
617 	EFSYS_PROBE1(fail1, int, rc);
618 
619 	/* Restore the old value */
620 	EFSYS_BAR_WRITEO(enp->en_esbp, rsp->address, &original, B_TRUE);
621 
622 	return (rc);
623 }
624 
625 	__checkReturn	int
626 efx_nic_test_tables(
627 	__in		efx_nic_t *enp,
628 	__in		efx_register_set_t *rsp,
629 	__in		efx_pattern_type_t pattern,
630 	__in		size_t count)
631 {
632 	efx_sram_pattern_fn_t func;
633 	unsigned int index;
634 	unsigned int address;
635 	efx_oword_t reg;
636 	efx_oword_t buf;
637 	int rc;
638 
639 	EFSYS_ASSERT(pattern < EFX_PATTERN_NTYPES);
640 	func = __efx_sram_pattern_fns[pattern];
641 
642 	while (count > 0) {
643 		/* Write */
644 		address = rsp->address;
645 		for (index = 0; index < rsp->rows; ++index) {
646 			func(2 * index + 0, B_FALSE, &reg.eo_qword[0]);
647 			func(2 * index + 1, B_FALSE, &reg.eo_qword[1]);
648 			EFX_AND_OWORD(reg, rsp->mask);
649 			EFSYS_BAR_WRITEO(enp->en_esbp, address, &reg, B_TRUE);
650 
651 			address += rsp->step;
652 		}
653 
654 		/* Read */
655 		address = rsp->address;
656 		for (index = 0; index < rsp->rows; ++index) {
657 			func(2 * index + 0, B_FALSE, &reg.eo_qword[0]);
658 			func(2 * index + 1, B_FALSE, &reg.eo_qword[1]);
659 			EFX_AND_OWORD(reg, rsp->mask);
660 			EFSYS_BAR_READO(enp->en_esbp, address, &buf, B_TRUE);
661 			if (memcmp(&reg, &buf, sizeof (reg))) {
662 				rc = EIO;
663 				goto fail1;
664 			}
665 
666 			address += rsp->step;
667 		}
668 
669 		++rsp;
670 		--count;
671 	}
672 
673 	return (0);
674 
675 fail1:
676 	EFSYS_PROBE1(fail1, int, rc);
677 
678 	return (rc);
679 }
680 
681 #endif	/* EFSYS_OPT_DIAG */
682