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