xref: /freebsd-src/sys/dev/sfxge/common/efx_intr.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1e948693eSPhilip Paeps /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
4929c7febSAndrew Rybchenko  * Copyright (c) 2007-2016 Solarflare Communications Inc.
53c838a9fSAndrew Rybchenko  * All rights reserved.
6e948693eSPhilip Paeps  *
7e948693eSPhilip Paeps  * Redistribution and use in source and binary forms, with or without
83c838a9fSAndrew Rybchenko  * modification, are permitted provided that the following conditions are met:
9e948693eSPhilip Paeps  *
103c838a9fSAndrew Rybchenko  * 1. Redistributions of source code must retain the above copyright notice,
113c838a9fSAndrew Rybchenko  *    this list of conditions and the following disclaimer.
123c838a9fSAndrew Rybchenko  * 2. Redistributions in binary form must reproduce the above copyright notice,
133c838a9fSAndrew Rybchenko  *    this list of conditions and the following disclaimer in the documentation
143c838a9fSAndrew Rybchenko  *    and/or other materials provided with the distribution.
153c838a9fSAndrew Rybchenko  *
163c838a9fSAndrew Rybchenko  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
173c838a9fSAndrew Rybchenko  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
183c838a9fSAndrew Rybchenko  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
193c838a9fSAndrew Rybchenko  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
203c838a9fSAndrew Rybchenko  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
213c838a9fSAndrew Rybchenko  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
223c838a9fSAndrew Rybchenko  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
233c838a9fSAndrew Rybchenko  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
243c838a9fSAndrew Rybchenko  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
253c838a9fSAndrew Rybchenko  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
263c838a9fSAndrew Rybchenko  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
273c838a9fSAndrew Rybchenko  *
283c838a9fSAndrew Rybchenko  * The views and conclusions contained in the software and documentation are
293c838a9fSAndrew Rybchenko  * those of the authors and should not be interpreted as representing official
303c838a9fSAndrew Rybchenko  * policies, either expressed or implied, of the FreeBSD Project.
31e948693eSPhilip Paeps  */
32e948693eSPhilip Paeps 
335dee87d7SPhilip Paeps #include <sys/cdefs.h>
34e948693eSPhilip Paeps #include "efx.h"
35e948693eSPhilip Paeps #include "efx_impl.h"
36e948693eSPhilip Paeps 
37e75412c9SAndrew Rybchenko #if EFSYS_OPT_SIENA
383c838a9fSAndrew Rybchenko 
39460cb568SAndrew Rybchenko static	__checkReturn	efx_rc_t
40e7b2e8b0SAndrew Rybchenko siena_intr_init(
413c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp,
423c838a9fSAndrew Rybchenko 	__in		efx_intr_type_t type,
433c838a9fSAndrew Rybchenko 	__in		efsys_mem_t *esmp);
443c838a9fSAndrew Rybchenko 
453c838a9fSAndrew Rybchenko static			void
46e7b2e8b0SAndrew Rybchenko siena_intr_enable(
473c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp);
483c838a9fSAndrew Rybchenko 
493c838a9fSAndrew Rybchenko static			void
50e7b2e8b0SAndrew Rybchenko siena_intr_disable(
513c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp);
523c838a9fSAndrew Rybchenko 
533c838a9fSAndrew Rybchenko static			void
54e7b2e8b0SAndrew Rybchenko siena_intr_disable_unlocked(
553c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp);
563c838a9fSAndrew Rybchenko 
57460cb568SAndrew Rybchenko static	__checkReturn	efx_rc_t
58e7b2e8b0SAndrew Rybchenko siena_intr_trigger(
593c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp,
603c838a9fSAndrew Rybchenko 	__in		unsigned int level);
613c838a9fSAndrew Rybchenko 
623c838a9fSAndrew Rybchenko static			void
63e7b2e8b0SAndrew Rybchenko siena_intr_fini(
643c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp);
653c838a9fSAndrew Rybchenko 
660c24a07eSAndrew Rybchenko static			void
67e7b2e8b0SAndrew Rybchenko siena_intr_status_line(
680c24a07eSAndrew Rybchenko 	__in		efx_nic_t *enp,
690c24a07eSAndrew Rybchenko 	__out		boolean_t *fatalp,
700c24a07eSAndrew Rybchenko 	__out		uint32_t *qmaskp);
710c24a07eSAndrew Rybchenko 
720c24a07eSAndrew Rybchenko static			void
73e7b2e8b0SAndrew Rybchenko siena_intr_status_message(
740c24a07eSAndrew Rybchenko 	__in		efx_nic_t *enp,
750c24a07eSAndrew Rybchenko 	__in		unsigned int message,
760c24a07eSAndrew Rybchenko 	__out		boolean_t *fatalp);
770c24a07eSAndrew Rybchenko 
780c24a07eSAndrew Rybchenko static			void
79e7b2e8b0SAndrew Rybchenko siena_intr_fatal(
800c24a07eSAndrew Rybchenko 	__in		efx_nic_t *enp);
813c838a9fSAndrew Rybchenko 
823c838a9fSAndrew Rybchenko static	__checkReturn	boolean_t
83e7b2e8b0SAndrew Rybchenko siena_intr_check_fatal(
843c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp);
853c838a9fSAndrew Rybchenko 
86e75412c9SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
873c838a9fSAndrew Rybchenko 
883c838a9fSAndrew Rybchenko #if EFSYS_OPT_SIENA
89ec831f7fSAndrew Rybchenko static const efx_intr_ops_t	__efx_intr_siena_ops = {
90e7b2e8b0SAndrew Rybchenko 	siena_intr_init,		/* eio_init */
91e7b2e8b0SAndrew Rybchenko 	siena_intr_enable,		/* eio_enable */
92e7b2e8b0SAndrew Rybchenko 	siena_intr_disable,		/* eio_disable */
93e7b2e8b0SAndrew Rybchenko 	siena_intr_disable_unlocked,	/* eio_disable_unlocked */
94e7b2e8b0SAndrew Rybchenko 	siena_intr_trigger,		/* eio_trigger */
95e7b2e8b0SAndrew Rybchenko 	siena_intr_status_line,		/* eio_status_line */
96e7b2e8b0SAndrew Rybchenko 	siena_intr_status_message,	/* eio_status_message */
97e7b2e8b0SAndrew Rybchenko 	siena_intr_fatal,		/* eio_fatal */
98e7b2e8b0SAndrew Rybchenko 	siena_intr_fini,		/* eio_fini */
993c838a9fSAndrew Rybchenko };
1003c838a9fSAndrew Rybchenko #endif	/* EFSYS_OPT_SIENA */
1013c838a9fSAndrew Rybchenko 
1021bef83eaSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
103ec831f7fSAndrew Rybchenko static const efx_intr_ops_t	__efx_intr_ef10_ops = {
10415f20ea6SAndrew Rybchenko 	ef10_intr_init,			/* eio_init */
10515f20ea6SAndrew Rybchenko 	ef10_intr_enable,		/* eio_enable */
10615f20ea6SAndrew Rybchenko 	ef10_intr_disable,		/* eio_disable */
10715f20ea6SAndrew Rybchenko 	ef10_intr_disable_unlocked,	/* eio_disable_unlocked */
10815f20ea6SAndrew Rybchenko 	ef10_intr_trigger,		/* eio_trigger */
1090c24a07eSAndrew Rybchenko 	ef10_intr_status_line,		/* eio_status_line */
1100c24a07eSAndrew Rybchenko 	ef10_intr_status_message,	/* eio_status_message */
1110c24a07eSAndrew Rybchenko 	ef10_intr_fatal,		/* eio_fatal */
11215f20ea6SAndrew Rybchenko 	ef10_intr_fini,			/* eio_fini */
1133c838a9fSAndrew Rybchenko };
1141bef83eaSAndrew Rybchenko #endif	/* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
1153c838a9fSAndrew Rybchenko 
116460cb568SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_intr_init(__in efx_nic_t * enp,__in efx_intr_type_t type,__in_opt efsys_mem_t * esmp)117e948693eSPhilip Paeps efx_intr_init(
118e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
119e948693eSPhilip Paeps 	__in		efx_intr_type_t type,
120d707fb20SAndrew Rybchenko 	__in_opt	efsys_mem_t *esmp)
121e948693eSPhilip Paeps {
122e948693eSPhilip Paeps 	efx_intr_t *eip = &(enp->en_intr);
123ec831f7fSAndrew Rybchenko 	const efx_intr_ops_t *eiop;
124460cb568SAndrew Rybchenko 	efx_rc_t rc;
125e948693eSPhilip Paeps 
126e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
127e948693eSPhilip Paeps 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
128e948693eSPhilip Paeps 
129e948693eSPhilip Paeps 	if (enp->en_mod_flags & EFX_MOD_INTR) {
130e948693eSPhilip Paeps 		rc = EINVAL;
131e948693eSPhilip Paeps 		goto fail1;
132e948693eSPhilip Paeps 	}
133e948693eSPhilip Paeps 
1343c838a9fSAndrew Rybchenko 	eip->ei_esmp = esmp;
1353c838a9fSAndrew Rybchenko 	eip->ei_type = type;
1363c838a9fSAndrew Rybchenko 	eip->ei_level = 0;
1373c838a9fSAndrew Rybchenko 
138e948693eSPhilip Paeps 	enp->en_mod_flags |= EFX_MOD_INTR;
139e948693eSPhilip Paeps 
1403c838a9fSAndrew Rybchenko 	switch (enp->en_family) {
1413c838a9fSAndrew Rybchenko #if EFSYS_OPT_SIENA
1423c838a9fSAndrew Rybchenko 	case EFX_FAMILY_SIENA:
143ec831f7fSAndrew Rybchenko 		eiop = &__efx_intr_siena_ops;
1443c838a9fSAndrew Rybchenko 		break;
1453c838a9fSAndrew Rybchenko #endif	/* EFSYS_OPT_SIENA */
1463c838a9fSAndrew Rybchenko 
1473c838a9fSAndrew Rybchenko #if EFSYS_OPT_HUNTINGTON
1483c838a9fSAndrew Rybchenko 	case EFX_FAMILY_HUNTINGTON:
149ec831f7fSAndrew Rybchenko 		eiop = &__efx_intr_ef10_ops;
1503c838a9fSAndrew Rybchenko 		break;
1513c838a9fSAndrew Rybchenko #endif	/* EFSYS_OPT_HUNTINGTON */
1523c838a9fSAndrew Rybchenko 
15315f20ea6SAndrew Rybchenko #if EFSYS_OPT_MEDFORD
15415f20ea6SAndrew Rybchenko 	case EFX_FAMILY_MEDFORD:
155ec831f7fSAndrew Rybchenko 		eiop = &__efx_intr_ef10_ops;
15615f20ea6SAndrew Rybchenko 		break;
15715f20ea6SAndrew Rybchenko #endif	/* EFSYS_OPT_MEDFORD */
15815f20ea6SAndrew Rybchenko 
1591bef83eaSAndrew Rybchenko #if EFSYS_OPT_MEDFORD2
1601bef83eaSAndrew Rybchenko 	case EFX_FAMILY_MEDFORD2:
1611bef83eaSAndrew Rybchenko 		eiop = &__efx_intr_ef10_ops;
1621bef83eaSAndrew Rybchenko 		break;
1631bef83eaSAndrew Rybchenko #endif	/* EFSYS_OPT_MEDFORD2 */
1641bef83eaSAndrew Rybchenko 
1653c838a9fSAndrew Rybchenko 	default:
1663c838a9fSAndrew Rybchenko 		EFSYS_ASSERT(B_FALSE);
1673c838a9fSAndrew Rybchenko 		rc = ENOTSUP;
1683c838a9fSAndrew Rybchenko 		goto fail2;
1693c838a9fSAndrew Rybchenko 	}
1703c838a9fSAndrew Rybchenko 
1713c838a9fSAndrew Rybchenko 	if ((rc = eiop->eio_init(enp, type, esmp)) != 0)
1723c838a9fSAndrew Rybchenko 		goto fail3;
1733c838a9fSAndrew Rybchenko 
1743c838a9fSAndrew Rybchenko 	eip->ei_eiop = eiop;
1753c838a9fSAndrew Rybchenko 
1763c838a9fSAndrew Rybchenko 	return (0);
1773c838a9fSAndrew Rybchenko 
1783c838a9fSAndrew Rybchenko fail3:
1793c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail3);
1803c838a9fSAndrew Rybchenko fail2:
1813c838a9fSAndrew Rybchenko 	EFSYS_PROBE(fail2);
1823c838a9fSAndrew Rybchenko fail1:
183460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
1843c838a9fSAndrew Rybchenko 
1853c838a9fSAndrew Rybchenko 	return (rc);
1863c838a9fSAndrew Rybchenko }
1873c838a9fSAndrew Rybchenko 
1883c838a9fSAndrew Rybchenko 		void
efx_intr_fini(__in efx_nic_t * enp)1893c838a9fSAndrew Rybchenko efx_intr_fini(
1903c838a9fSAndrew Rybchenko 	__in	efx_nic_t *enp)
1913c838a9fSAndrew Rybchenko {
1923c838a9fSAndrew Rybchenko 	efx_intr_t *eip = &(enp->en_intr);
193ec831f7fSAndrew Rybchenko 	const efx_intr_ops_t *eiop = eip->ei_eiop;
1943c838a9fSAndrew Rybchenko 
1953c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
1963c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_NIC);
1973c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
1983c838a9fSAndrew Rybchenko 
1993c838a9fSAndrew Rybchenko 	eiop->eio_fini(enp);
2003c838a9fSAndrew Rybchenko 
2013c838a9fSAndrew Rybchenko 	enp->en_mod_flags &= ~EFX_MOD_INTR;
2023c838a9fSAndrew Rybchenko }
2033c838a9fSAndrew Rybchenko 
2043c838a9fSAndrew Rybchenko 			void
efx_intr_enable(__in efx_nic_t * enp)2053c838a9fSAndrew Rybchenko efx_intr_enable(
2063c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp)
2073c838a9fSAndrew Rybchenko {
2083c838a9fSAndrew Rybchenko 	efx_intr_t *eip = &(enp->en_intr);
209ec831f7fSAndrew Rybchenko 	const efx_intr_ops_t *eiop = eip->ei_eiop;
2103c838a9fSAndrew Rybchenko 
2113c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2123c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
2133c838a9fSAndrew Rybchenko 
2143c838a9fSAndrew Rybchenko 	eiop->eio_enable(enp);
2153c838a9fSAndrew Rybchenko }
2163c838a9fSAndrew Rybchenko 
2173c838a9fSAndrew Rybchenko 			void
efx_intr_disable(__in efx_nic_t * enp)2183c838a9fSAndrew Rybchenko efx_intr_disable(
2193c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp)
2203c838a9fSAndrew Rybchenko {
2213c838a9fSAndrew Rybchenko 	efx_intr_t *eip = &(enp->en_intr);
222ec831f7fSAndrew Rybchenko 	const efx_intr_ops_t *eiop = eip->ei_eiop;
2233c838a9fSAndrew Rybchenko 
2243c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2253c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
2263c838a9fSAndrew Rybchenko 
2273c838a9fSAndrew Rybchenko 	eiop->eio_disable(enp);
2283c838a9fSAndrew Rybchenko }
2293c838a9fSAndrew Rybchenko 
2303c838a9fSAndrew Rybchenko 			void
efx_intr_disable_unlocked(__in efx_nic_t * enp)2313c838a9fSAndrew Rybchenko efx_intr_disable_unlocked(
2323c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp)
2333c838a9fSAndrew Rybchenko {
2343c838a9fSAndrew Rybchenko 	efx_intr_t *eip = &(enp->en_intr);
235ec831f7fSAndrew Rybchenko 	const efx_intr_ops_t *eiop = eip->ei_eiop;
2363c838a9fSAndrew Rybchenko 
2373c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2383c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
2393c838a9fSAndrew Rybchenko 
2403c838a9fSAndrew Rybchenko 	eiop->eio_disable_unlocked(enp);
2413c838a9fSAndrew Rybchenko }
2423c838a9fSAndrew Rybchenko 
243460cb568SAndrew Rybchenko 	__checkReturn	efx_rc_t
efx_intr_trigger(__in efx_nic_t * enp,__in unsigned int level)2443c838a9fSAndrew Rybchenko efx_intr_trigger(
2453c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp,
2463c838a9fSAndrew Rybchenko 	__in		unsigned int level)
2473c838a9fSAndrew Rybchenko {
2483c838a9fSAndrew Rybchenko 	efx_intr_t *eip = &(enp->en_intr);
249ec831f7fSAndrew Rybchenko 	const efx_intr_ops_t *eiop = eip->ei_eiop;
2503c838a9fSAndrew Rybchenko 
2513c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2523c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
2533c838a9fSAndrew Rybchenko 
2543c838a9fSAndrew Rybchenko 	return (eiop->eio_trigger(enp, level));
2553c838a9fSAndrew Rybchenko }
2563c838a9fSAndrew Rybchenko 
2573c838a9fSAndrew Rybchenko 			void
efx_intr_status_line(__in efx_nic_t * enp,__out boolean_t * fatalp,__out uint32_t * qmaskp)2583c838a9fSAndrew Rybchenko efx_intr_status_line(
2593c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp,
2603c838a9fSAndrew Rybchenko 	__out		boolean_t *fatalp,
2613c838a9fSAndrew Rybchenko 	__out		uint32_t *qmaskp)
2623c838a9fSAndrew Rybchenko {
2633c838a9fSAndrew Rybchenko 	efx_intr_t *eip = &(enp->en_intr);
264ec831f7fSAndrew Rybchenko 	const efx_intr_ops_t *eiop = eip->ei_eiop;
2653c838a9fSAndrew Rybchenko 
2663c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2673c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
2683c838a9fSAndrew Rybchenko 
2690c24a07eSAndrew Rybchenko 	eiop->eio_status_line(enp, fatalp, qmaskp);
2703c838a9fSAndrew Rybchenko }
2713c838a9fSAndrew Rybchenko 
2723c838a9fSAndrew Rybchenko 			void
efx_intr_status_message(__in efx_nic_t * enp,__in unsigned int message,__out boolean_t * fatalp)2733c838a9fSAndrew Rybchenko efx_intr_status_message(
2743c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp,
2753c838a9fSAndrew Rybchenko 	__in		unsigned int message,
2763c838a9fSAndrew Rybchenko 	__out		boolean_t *fatalp)
2773c838a9fSAndrew Rybchenko {
2783c838a9fSAndrew Rybchenko 	efx_intr_t *eip = &(enp->en_intr);
279ec831f7fSAndrew Rybchenko 	const efx_intr_ops_t *eiop = eip->ei_eiop;
2803c838a9fSAndrew Rybchenko 
2813c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2823c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
2833c838a9fSAndrew Rybchenko 
2840c24a07eSAndrew Rybchenko 	eiop->eio_status_message(enp, message, fatalp);
2853c838a9fSAndrew Rybchenko }
2863c838a9fSAndrew Rybchenko 
2873c838a9fSAndrew Rybchenko 		void
efx_intr_fatal(__in efx_nic_t * enp)2883c838a9fSAndrew Rybchenko efx_intr_fatal(
2893c838a9fSAndrew Rybchenko 	__in	efx_nic_t *enp)
2903c838a9fSAndrew Rybchenko {
2910c24a07eSAndrew Rybchenko 	efx_intr_t *eip = &(enp->en_intr);
292ec831f7fSAndrew Rybchenko 	const efx_intr_ops_t *eiop = eip->ei_eiop;
2930c24a07eSAndrew Rybchenko 
2943c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
2953c838a9fSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
2963c838a9fSAndrew Rybchenko 
2970c24a07eSAndrew Rybchenko 	eiop->eio_fatal(enp);
2983c838a9fSAndrew Rybchenko }
2993c838a9fSAndrew Rybchenko 
3003c838a9fSAndrew Rybchenko /* ************************************************************************* */
3013c838a9fSAndrew Rybchenko /* ************************************************************************* */
3023c838a9fSAndrew Rybchenko /* ************************************************************************* */
3033c838a9fSAndrew Rybchenko 
304e75412c9SAndrew Rybchenko #if EFSYS_OPT_SIENA
3053c838a9fSAndrew Rybchenko 
306460cb568SAndrew Rybchenko static	__checkReturn	efx_rc_t
siena_intr_init(__in efx_nic_t * enp,__in efx_intr_type_t type,__in efsys_mem_t * esmp)307e7b2e8b0SAndrew Rybchenko siena_intr_init(
3083c838a9fSAndrew Rybchenko 	__in		efx_nic_t *enp,
3093c838a9fSAndrew Rybchenko 	__in		efx_intr_type_t type,
3103c838a9fSAndrew Rybchenko 	__in		efsys_mem_t *esmp)
3113c838a9fSAndrew Rybchenko {
3123c838a9fSAndrew Rybchenko 	efx_intr_t *eip = &(enp->en_intr);
3133c838a9fSAndrew Rybchenko 	efx_oword_t oword;
3144aaefb95SAndrew Rybchenko 	efx_rc_t rc;
3154aaefb95SAndrew Rybchenko 
3164aaefb95SAndrew Rybchenko 	if ((esmp == NULL) || (EFSYS_MEM_SIZE(esmp) < EFX_INTR_SIZE)) {
3174aaefb95SAndrew Rybchenko 		rc = EINVAL;
3184aaefb95SAndrew Rybchenko 		goto fail1;
3194aaefb95SAndrew Rybchenko 	}
320e948693eSPhilip Paeps 
321e948693eSPhilip Paeps 	/*
322e948693eSPhilip Paeps 	 * bug17213 workaround.
323e948693eSPhilip Paeps 	 *
324e948693eSPhilip Paeps 	 * Under legacy interrupts, don't share a level between fatal
325e948693eSPhilip Paeps 	 * interrupts and event queue interrupts. Under MSI-X, they
326e948693eSPhilip Paeps 	 * must share, or we won't get an interrupt.
327e948693eSPhilip Paeps 	 */
328e948693eSPhilip Paeps 	if (enp->en_family == EFX_FAMILY_SIENA &&
329e948693eSPhilip Paeps 	    eip->ei_type == EFX_INTR_LINE)
330e948693eSPhilip Paeps 		eip->ei_level = 0x1f;
331e948693eSPhilip Paeps 	else
332e948693eSPhilip Paeps 		eip->ei_level = 0;
333e948693eSPhilip Paeps 
334e948693eSPhilip Paeps 	/* Enable all the genuinely fatal interrupts */
335e948693eSPhilip Paeps 	EFX_SET_OWORD(oword);
336e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_ILL_ADR_INT_KER_EN, 0);
337e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_RBUF_OWN_INT_KER_EN, 0);
338e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_TBUF_OWN_INT_KER_EN, 0);
339e948693eSPhilip Paeps 	if (enp->en_family >= EFX_FAMILY_SIENA)
340e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword, FRF_CZ_SRAM_PERR_INT_P_KER_EN, 0);
341e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_FATAL_INTR_REG_KER, &oword);
342e948693eSPhilip Paeps 
343e948693eSPhilip Paeps 	/* Set up the interrupt address register */
344e948693eSPhilip Paeps 	EFX_POPULATE_OWORD_3(oword,
345e948693eSPhilip Paeps 	    FRF_AZ_NORM_INT_VEC_DIS_KER, (type == EFX_INTR_MESSAGE) ? 1 : 0,
346e948693eSPhilip Paeps 	    FRF_AZ_INT_ADR_KER_DW0, EFSYS_MEM_ADDR(esmp) & 0xffffffff,
347e948693eSPhilip Paeps 	    FRF_AZ_INT_ADR_KER_DW1, EFSYS_MEM_ADDR(esmp) >> 32);
348e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
349e948693eSPhilip Paeps 
350e948693eSPhilip Paeps 	return (0);
3514aaefb95SAndrew Rybchenko 
3524aaefb95SAndrew Rybchenko fail1:
3534aaefb95SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
3544aaefb95SAndrew Rybchenko 
3554aaefb95SAndrew Rybchenko 	return (rc);
356e948693eSPhilip Paeps }
357e948693eSPhilip Paeps 
3583c838a9fSAndrew Rybchenko static			void
siena_intr_enable(__in efx_nic_t * enp)359e7b2e8b0SAndrew Rybchenko siena_intr_enable(
360e948693eSPhilip Paeps 	__in		efx_nic_t *enp)
361e948693eSPhilip Paeps {
362e948693eSPhilip Paeps 	efx_intr_t *eip = &(enp->en_intr);
363e948693eSPhilip Paeps 	efx_oword_t oword;
364e948693eSPhilip Paeps 
365e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
366e948693eSPhilip Paeps 
367e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
368e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 1);
369e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
370e948693eSPhilip Paeps }
371e948693eSPhilip Paeps 
3723c838a9fSAndrew Rybchenko static			void
siena_intr_disable(__in efx_nic_t * enp)373e7b2e8b0SAndrew Rybchenko siena_intr_disable(
374e948693eSPhilip Paeps 	__in		efx_nic_t *enp)
375e948693eSPhilip Paeps {
376e948693eSPhilip Paeps 	efx_oword_t oword;
377e948693eSPhilip Paeps 
378e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
379e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
380e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
381e948693eSPhilip Paeps 
382e948693eSPhilip Paeps 	EFSYS_SPIN(10);
383e948693eSPhilip Paeps }
384e948693eSPhilip Paeps 
3853c838a9fSAndrew Rybchenko static			void
siena_intr_disable_unlocked(__in efx_nic_t * enp)386e7b2e8b0SAndrew Rybchenko siena_intr_disable_unlocked(
387e948693eSPhilip Paeps 	__in		efx_nic_t *enp)
388e948693eSPhilip Paeps {
389e948693eSPhilip Paeps 	efx_oword_t oword;
390e948693eSPhilip Paeps 
391e948693eSPhilip Paeps 	EFSYS_BAR_READO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
392e948693eSPhilip Paeps 			&oword, B_FALSE);
393e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_DRV_INT_EN_KER, 0);
394e948693eSPhilip Paeps 	EFSYS_BAR_WRITEO(enp->en_esbp, FR_AZ_INT_EN_REG_KER_OFST,
395e948693eSPhilip Paeps 	    &oword, B_FALSE);
396e948693eSPhilip Paeps }
397e948693eSPhilip Paeps 
398460cb568SAndrew Rybchenko static	__checkReturn	efx_rc_t
siena_intr_trigger(__in efx_nic_t * enp,__in unsigned int level)399e7b2e8b0SAndrew Rybchenko siena_intr_trigger(
400e948693eSPhilip Paeps 	__in		efx_nic_t *enp,
401e948693eSPhilip Paeps 	__in		unsigned int level)
402e948693eSPhilip Paeps {
403e948693eSPhilip Paeps 	efx_intr_t *eip = &(enp->en_intr);
404e948693eSPhilip Paeps 	efx_oword_t oword;
405e948693eSPhilip Paeps 	unsigned int count;
406e948693eSPhilip Paeps 	uint32_t sel;
407460cb568SAndrew Rybchenko 	efx_rc_t rc;
408e948693eSPhilip Paeps 
409e948693eSPhilip Paeps 	/* bug16757: No event queues can be initialized */
410e948693eSPhilip Paeps 	EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_EV));
411e948693eSPhilip Paeps 
4123c838a9fSAndrew Rybchenko 	if (level >= EFX_NINTR_SIENA) {
413e948693eSPhilip Paeps 		rc = EINVAL;
414e948693eSPhilip Paeps 		goto fail1;
415e948693eSPhilip Paeps 	}
416e948693eSPhilip Paeps 
417e948693eSPhilip Paeps 	if (level > EFX_MASK32(FRF_AZ_KER_INT_LEVE_SEL))
418e948693eSPhilip Paeps 		return (ENOTSUP); /* avoid EFSYS_PROBE() */
419e948693eSPhilip Paeps 
420e948693eSPhilip Paeps 	sel = level;
421e948693eSPhilip Paeps 
422e948693eSPhilip Paeps 	/* Trigger a test interrupt */
423e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
424e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, sel);
425e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER, 1);
426e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
427e948693eSPhilip Paeps 
428e948693eSPhilip Paeps 	/*
429e948693eSPhilip Paeps 	 * Wait up to 100ms for the interrupt to be raised before restoring
430e948693eSPhilip Paeps 	 * KER_INT_LEVE_SEL. Ignore a failure to raise (the caller will
431e948693eSPhilip Paeps 	 * observe this soon enough anyway), but always reset KER_INT_LEVE_SEL
432e948693eSPhilip Paeps 	 */
433e948693eSPhilip Paeps 	count = 0;
434e948693eSPhilip Paeps 	do {
435e948693eSPhilip Paeps 		EFSYS_SPIN(100);	/* 100us */
436e948693eSPhilip Paeps 
437e948693eSPhilip Paeps 		EFX_BAR_READO(enp, FR_AZ_INT_EN_REG_KER, &oword);
438e948693eSPhilip Paeps 	} while (EFX_OWORD_FIELD(oword, FRF_AZ_KER_INT_KER) && ++count < 1000);
439e948693eSPhilip Paeps 
440e948693eSPhilip Paeps 	EFX_SET_OWORD_FIELD(oword, FRF_AZ_KER_INT_LEVE_SEL, eip->ei_level);
441e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_INT_EN_REG_KER, &oword);
442e948693eSPhilip Paeps 
443e948693eSPhilip Paeps 	return (0);
444e948693eSPhilip Paeps 
445e948693eSPhilip Paeps fail1:
446460cb568SAndrew Rybchenko 	EFSYS_PROBE1(fail1, efx_rc_t, rc);
447e948693eSPhilip Paeps 
448e948693eSPhilip Paeps 	return (rc);
449e948693eSPhilip Paeps }
450e948693eSPhilip Paeps 
451e948693eSPhilip Paeps static	__checkReturn	boolean_t
siena_intr_check_fatal(__in efx_nic_t * enp)452e7b2e8b0SAndrew Rybchenko siena_intr_check_fatal(
453e948693eSPhilip Paeps 	__in		efx_nic_t *enp)
454e948693eSPhilip Paeps {
455e948693eSPhilip Paeps 	efx_intr_t *eip = &(enp->en_intr);
456e948693eSPhilip Paeps 	efsys_mem_t *esmp = eip->ei_esmp;
457e948693eSPhilip Paeps 	efx_oword_t oword;
458e948693eSPhilip Paeps 
459e948693eSPhilip Paeps 	/* Read the syndrome */
460e948693eSPhilip Paeps 	EFSYS_MEM_READO(esmp, 0, &oword);
461e948693eSPhilip Paeps 
462e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT) != 0) {
463e948693eSPhilip Paeps 		EFSYS_PROBE(fatal);
464e948693eSPhilip Paeps 
465e948693eSPhilip Paeps 		/* Clear the fatal interrupt condition */
466e948693eSPhilip Paeps 		EFX_SET_OWORD_FIELD(oword, FSF_AZ_NET_IVEC_FATAL_INT, 0);
467e948693eSPhilip Paeps 		EFSYS_MEM_WRITEO(esmp, 0, &oword);
468e948693eSPhilip Paeps 
469e948693eSPhilip Paeps 		return (B_TRUE);
470e948693eSPhilip Paeps 	}
471e948693eSPhilip Paeps 
472e948693eSPhilip Paeps 	return (B_FALSE);
473e948693eSPhilip Paeps }
474e948693eSPhilip Paeps 
4753c838a9fSAndrew Rybchenko static			void
siena_intr_status_line(__in efx_nic_t * enp,__out boolean_t * fatalp,__out uint32_t * qmaskp)476e7b2e8b0SAndrew Rybchenko siena_intr_status_line(
4770c24a07eSAndrew Rybchenko 	__in		efx_nic_t *enp,
4780c24a07eSAndrew Rybchenko 	__out		boolean_t *fatalp,
4790c24a07eSAndrew Rybchenko 	__out		uint32_t *qmaskp)
4800c24a07eSAndrew Rybchenko {
4810c24a07eSAndrew Rybchenko 	efx_intr_t *eip = &(enp->en_intr);
4820c24a07eSAndrew Rybchenko 	efx_dword_t dword;
4830c24a07eSAndrew Rybchenko 
4840c24a07eSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
4850c24a07eSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
4860c24a07eSAndrew Rybchenko 
4870c24a07eSAndrew Rybchenko 	/*
4880c24a07eSAndrew Rybchenko 	 * Read the queue mask and implicitly acknowledge the
4890c24a07eSAndrew Rybchenko 	 * interrupt.
4900c24a07eSAndrew Rybchenko 	 */
4910c24a07eSAndrew Rybchenko 	EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE);
4920c24a07eSAndrew Rybchenko 	*qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
4930c24a07eSAndrew Rybchenko 
4940c24a07eSAndrew Rybchenko 	EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
4950c24a07eSAndrew Rybchenko 
4960c24a07eSAndrew Rybchenko 	if (*qmaskp & (1U << eip->ei_level))
497e7b2e8b0SAndrew Rybchenko 		*fatalp = siena_intr_check_fatal(enp);
4980c24a07eSAndrew Rybchenko 	else
4990c24a07eSAndrew Rybchenko 		*fatalp = B_FALSE;
5000c24a07eSAndrew Rybchenko }
5010c24a07eSAndrew Rybchenko 
5020c24a07eSAndrew Rybchenko static			void
siena_intr_status_message(__in efx_nic_t * enp,__in unsigned int message,__out boolean_t * fatalp)503e7b2e8b0SAndrew Rybchenko siena_intr_status_message(
5040c24a07eSAndrew Rybchenko 	__in		efx_nic_t *enp,
5050c24a07eSAndrew Rybchenko 	__in		unsigned int message,
5060c24a07eSAndrew Rybchenko 	__out		boolean_t *fatalp)
5070c24a07eSAndrew Rybchenko {
5080c24a07eSAndrew Rybchenko 	efx_intr_t *eip = &(enp->en_intr);
5090c24a07eSAndrew Rybchenko 
5100c24a07eSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
5110c24a07eSAndrew Rybchenko 	EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
5120c24a07eSAndrew Rybchenko 
5130c24a07eSAndrew Rybchenko 	if (message == eip->ei_level)
514e7b2e8b0SAndrew Rybchenko 		*fatalp = siena_intr_check_fatal(enp);
5150c24a07eSAndrew Rybchenko 	else
5160c24a07eSAndrew Rybchenko 		*fatalp = B_FALSE;
5170c24a07eSAndrew Rybchenko }
5180c24a07eSAndrew Rybchenko 
5190c24a07eSAndrew Rybchenko static		void
siena_intr_fatal(__in efx_nic_t * enp)520e7b2e8b0SAndrew Rybchenko siena_intr_fatal(
521e948693eSPhilip Paeps 	__in	efx_nic_t *enp)
522e948693eSPhilip Paeps {
523e948693eSPhilip Paeps #if EFSYS_OPT_DECODE_INTR_FATAL
524e948693eSPhilip Paeps 	efx_oword_t fatal;
525e948693eSPhilip Paeps 	efx_oword_t mem_per;
526e948693eSPhilip Paeps 
527e948693eSPhilip Paeps 	EFX_BAR_READO(enp, FR_AZ_FATAL_INTR_REG_KER, &fatal);
528e948693eSPhilip Paeps 	EFX_ZERO_OWORD(mem_per);
529e948693eSPhilip Paeps 
530e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0 ||
531e948693eSPhilip Paeps 	    EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
532e948693eSPhilip Paeps 		EFX_BAR_READO(enp, FR_AZ_MEM_STAT_REG, &mem_per);
533e948693eSPhilip Paeps 
534e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRAM_OOB_INT_KER) != 0)
535e948693eSPhilip Paeps 		EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_OOB, 0, 0);
536e948693eSPhilip Paeps 
537e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_BUFID_DC_OOB_INT_KER) != 0)
538e948693eSPhilip Paeps 		EFSYS_ERR(enp->en_esip, EFX_ERR_BUFID_DC_OOB, 0, 0);
539e948693eSPhilip Paeps 
540e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_MEM_PERR_INT_KER) != 0)
541e948693eSPhilip Paeps 		EFSYS_ERR(enp->en_esip, EFX_ERR_MEM_PERR,
542e948693eSPhilip Paeps 		    EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
543e948693eSPhilip Paeps 		    EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
544e948693eSPhilip Paeps 
545e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_RBUF_OWN_INT_KER) != 0)
546e948693eSPhilip Paeps 		EFSYS_ERR(enp->en_esip, EFX_ERR_RBUF_OWN, 0, 0);
547e948693eSPhilip Paeps 
548e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_TBUF_OWN_INT_KER) != 0)
549e948693eSPhilip Paeps 		EFSYS_ERR(enp->en_esip, EFX_ERR_TBUF_OWN, 0, 0);
550e948693eSPhilip Paeps 
551e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_RDESCQ_OWN_INT_KER) != 0)
552e948693eSPhilip Paeps 		EFSYS_ERR(enp->en_esip, EFX_ERR_RDESQ_OWN, 0, 0);
553e948693eSPhilip Paeps 
554e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_TDESCQ_OWN_INT_KER) != 0)
555e948693eSPhilip Paeps 		EFSYS_ERR(enp->en_esip, EFX_ERR_TDESQ_OWN, 0, 0);
556e948693eSPhilip Paeps 
557e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVQ_OWN_INT_KER) != 0)
558e948693eSPhilip Paeps 		EFSYS_ERR(enp->en_esip, EFX_ERR_EVQ_OWN, 0, 0);
559e948693eSPhilip Paeps 
560e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_EVF_OFLO_INT_KER) != 0)
561e948693eSPhilip Paeps 		EFSYS_ERR(enp->en_esip, EFX_ERR_EVFF_OFLO, 0, 0);
562e948693eSPhilip Paeps 
563e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_ILL_ADR_INT_KER) != 0)
564e948693eSPhilip Paeps 		EFSYS_ERR(enp->en_esip, EFX_ERR_ILL_ADDR, 0, 0);
565e948693eSPhilip Paeps 
566e948693eSPhilip Paeps 	if (EFX_OWORD_FIELD(fatal, FRF_AZ_SRM_PERR_INT_KER) != 0)
567e948693eSPhilip Paeps 		EFSYS_ERR(enp->en_esip, EFX_ERR_SRAM_PERR,
568e948693eSPhilip Paeps 		    EFX_OWORD_FIELD(mem_per, EFX_DWORD_0),
569e948693eSPhilip Paeps 		    EFX_OWORD_FIELD(mem_per, EFX_DWORD_1));
570e948693eSPhilip Paeps #else
571e948693eSPhilip Paeps 	EFSYS_ASSERT(0);
572e948693eSPhilip Paeps #endif
573e948693eSPhilip Paeps }
574e948693eSPhilip Paeps 
5753c838a9fSAndrew Rybchenko static		void
siena_intr_fini(__in efx_nic_t * enp)576e7b2e8b0SAndrew Rybchenko siena_intr_fini(
577e948693eSPhilip Paeps 	__in	efx_nic_t *enp)
578e948693eSPhilip Paeps {
579e948693eSPhilip Paeps 	efx_oword_t oword;
580e948693eSPhilip Paeps 
581e948693eSPhilip Paeps 	/* Clear the interrupt address register */
582e948693eSPhilip Paeps 	EFX_ZERO_OWORD(oword);
583e948693eSPhilip Paeps 	EFX_BAR_WRITEO(enp, FR_AZ_INT_ADR_REG_KER, &oword);
584e948693eSPhilip Paeps }
5853c838a9fSAndrew Rybchenko 
586e75412c9SAndrew Rybchenko #endif /* EFSYS_OPT_SIENA */
587