sfxge: fix interrupt handling for Medford

Submitted by:   Andy Moreton <amoreton at solarflare.com>
Reviewed by:    gnn
Sponsored by:   Solarflare Communications, Inc.
MFC after:      2 days
Differential Revision: https://reviews.freebsd.org/D4886
This commit is contained in:
Andrew Rybchenko 2016-01-12 15:28:59 +00:00
parent f5969609b9
commit 0c24a07e20
4 changed files with 138 additions and 48 deletions

View File

@ -342,6 +342,10 @@ typedef struct efx_intr_ops_s {
void (*eio_disable)(efx_nic_t *);
void (*eio_disable_unlocked)(efx_nic_t *);
efx_rc_t (*eio_trigger)(efx_nic_t *, unsigned int);
void (*eio_status_line)(efx_nic_t *, boolean_t *, uint32_t *);
void (*eio_status_message)(efx_nic_t *, unsigned int,
boolean_t *);
void (*eio_fatal)(efx_nic_t *);
void (*eio_fini)(efx_nic_t *);
} efx_intr_ops_t;

View File

@ -67,14 +67,26 @@ static void
falconsiena_intr_fini(
__in efx_nic_t *enp);
static void
falconsiena_intr_status_line(
__in efx_nic_t *enp,
__out boolean_t *fatalp,
__out uint32_t *qmaskp);
static void
falconsiena_intr_status_message(
__in efx_nic_t *enp,
__in unsigned int message,
__out boolean_t *fatalp);
static void
falconsiena_intr_fatal(
__in efx_nic_t *enp);
static __checkReturn boolean_t
falconsiena_intr_check_fatal(
__in efx_nic_t *enp);
static void
falconsiena_intr_fatal(
__in efx_nic_t *enp);
#endif /* EFSYS_OPT_FALCON || EFSYS_OPT_SIENA */
@ -86,6 +98,9 @@ static efx_intr_ops_t __efx_intr_falcon_ops = {
falconsiena_intr_disable, /* eio_disable */
falconsiena_intr_disable_unlocked, /* eio_disable_unlocked */
falconsiena_intr_trigger, /* eio_trigger */
falconsiena_intr_status_line, /* eio_status_line */
falconsiena_intr_status_message, /* eio_status_message */
falconsiena_intr_fatal, /* eio_fatal */
falconsiena_intr_fini, /* eio_fini */
};
#endif /* EFSYS_OPT_FALCON */
@ -97,6 +112,9 @@ static efx_intr_ops_t __efx_intr_siena_ops = {
falconsiena_intr_disable, /* eio_disable */
falconsiena_intr_disable_unlocked, /* eio_disable_unlocked */
falconsiena_intr_trigger, /* eio_trigger */
falconsiena_intr_status_line, /* eio_status_line */
falconsiena_intr_status_message, /* eio_status_message */
falconsiena_intr_fatal, /* eio_fatal */
falconsiena_intr_fini, /* eio_fini */
};
#endif /* EFSYS_OPT_SIENA */
@ -108,6 +126,9 @@ static efx_intr_ops_t __efx_intr_ef10_ops = {
ef10_intr_disable, /* eio_disable */
ef10_intr_disable_unlocked, /* eio_disable_unlocked */
ef10_intr_trigger, /* eio_trigger */
ef10_intr_status_line, /* eio_status_line */
ef10_intr_status_message, /* eio_status_message */
ef10_intr_fatal, /* eio_fatal */
ef10_intr_fini, /* eio_fini */
};
#endif /* EFSYS_OPT_HUNTINGTON || EFSYS_OPT_MEDFORD */
@ -261,35 +282,12 @@ efx_intr_status_line(
__out uint32_t *qmaskp)
{
efx_intr_t *eip = &(enp->en_intr);
efx_dword_t dword;
efx_intr_ops_t *eiop = eip->ei_eiop;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
/* Ensure Huntington and Falcon/Siena ISR at same location */
EFX_STATIC_ASSERT(FR_BZ_INT_ISR0_REG_OFST ==
ER_DZ_BIU_INT_ISR_REG_OFST);
/*
* Read the queue mask and implicitly acknowledge the
* interrupt.
*/
EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE);
*qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
#if EFSYS_OPT_HUNTINGTON
if (enp->en_family == EFX_FAMILY_HUNTINGTON) {
/* Huntington reports fatal errors via events */
*fatalp = B_FALSE;
return;
}
#endif
if (*qmaskp & (1U << eip->ei_level))
*fatalp = falconsiena_intr_check_fatal(enp);
else
*fatalp = B_FALSE;
eiop->eio_status_line(enp, fatalp, qmaskp);
}
void
@ -299,39 +297,25 @@ efx_intr_status_message(
__out boolean_t *fatalp)
{
efx_intr_t *eip = &(enp->en_intr);
efx_intr_ops_t *eiop = eip->ei_eiop;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
#if EFSYS_OPT_HUNTINGTON
if (enp->en_family == EFX_FAMILY_HUNTINGTON) {
/* Huntington reports fatal errors via events */
*fatalp = B_FALSE;
return;
}
#endif
if (message == eip->ei_level)
*fatalp = falconsiena_intr_check_fatal(enp);
else
*fatalp = B_FALSE;
eiop->eio_status_message(enp, message, fatalp);
}
void
efx_intr_fatal(
__in efx_nic_t *enp)
{
efx_intr_t *eip = &(enp->en_intr);
efx_intr_ops_t *eiop = eip->ei_eiop;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
#if EFSYS_OPT_HUNTINGTON
if (enp->en_family == EFX_FAMILY_HUNTINGTON) {
/* Huntington reports fatal errors via events */
return;
}
#endif
#if EFSYS_OPT_FALCON || EFSYS_OPT_SIENA
falconsiena_intr_fatal(enp);
#endif
eiop->eio_fatal(enp);
}
@ -514,6 +498,51 @@ falconsiena_intr_check_fatal(
return (B_FALSE);
}
static void
falconsiena_intr_status_line(
__in efx_nic_t *enp,
__out boolean_t *fatalp,
__out uint32_t *qmaskp)
{
efx_intr_t *eip = &(enp->en_intr);
efx_dword_t dword;
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
/*
* Read the queue mask and implicitly acknowledge the
* interrupt.
*/
EFX_BAR_READD(enp, FR_BZ_INT_ISR0_REG, &dword, B_FALSE);
*qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
if (*qmaskp & (1U << eip->ei_level))
*fatalp = falconsiena_intr_check_fatal(enp);
else
*fatalp = B_FALSE;
}
static void
falconsiena_intr_status_message(
__in efx_nic_t *enp,
__in unsigned int message,
__out boolean_t *fatalp)
{
efx_intr_t *eip = &(enp->en_intr);
EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_INTR);
if (message == eip->ei_level)
*fatalp = falconsiena_intr_check_fatal(enp);
else
*fatalp = B_FALSE;
}
static void
falconsiena_intr_fatal(
__in efx_nic_t *enp)

View File

@ -139,6 +139,21 @@ ef10_intr_trigger(
__in efx_nic_t *enp,
__in unsigned int level);
void
ef10_intr_status_line(
__in efx_nic_t *enp,
__out boolean_t *fatalp,
__out uint32_t *qmaskp);
void
ef10_intr_status_message(
__in efx_nic_t *enp,
__in unsigned int message,
__out boolean_t *fatalp);
void
ef10_intr_fatal(
__in efx_nic_t *enp);
void
ef10_intr_fini(
__in efx_nic_t *enp);

View File

@ -148,6 +148,48 @@ fail1:
return (rc);
}
void
ef10_intr_status_line(
__in efx_nic_t *enp,
__out boolean_t *fatalp,
__out uint32_t *qmaskp)
{
efx_dword_t dword;
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
enp->en_family == EFX_FAMILY_MEDFORD);
/* Read the queue mask and implicitly acknowledge the interrupt. */
EFX_BAR_READD(enp, ER_DZ_BIU_INT_ISR_REG, &dword, B_FALSE);
*qmaskp = EFX_DWORD_FIELD(dword, EFX_DWORD_0);
EFSYS_PROBE1(qmask, uint32_t, *qmaskp);
*fatalp = B_FALSE;
}
void
ef10_intr_status_message(
__in efx_nic_t *enp,
__in unsigned int message,
__out boolean_t *fatalp)
{
EFSYS_ASSERT(enp->en_family == EFX_FAMILY_HUNTINGTON ||
enp->en_family == EFX_FAMILY_MEDFORD);
_NOTE(ARGUNUSED(enp, message))
/* EF10 fatal errors are reported via events */
*fatalp = B_FALSE;
}
void
ef10_intr_fatal(
__in efx_nic_t *enp)
{
/* EF10 fatal errors are reported via events */
_NOTE(ARGUNUSED(enp))
}
void
ef10_intr_fini(