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