aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/asmc/asmc.c170
-rw-r--r--sys/dev/asmc/asmcmmio.c402
-rw-r--r--sys/dev/asmc/asmcmmio.h56
-rw-r--r--sys/dev/asmc/asmcvar.h5
-rw-r--r--sys/dev/bnxt/bnxt_en/bnxt_sriov.c39
-rw-r--r--sys/dev/bnxt/bnxt_en/bnxt_sriov.h4
-rw-r--r--sys/dev/bnxt/bnxt_en/if_bnxt.c2
-rw-r--r--sys/dev/cxgbe/adapter.h1
-rw-r--r--sys/dev/cxgbe/common/t4_hw.c1843
-rw-r--r--sys/dev/cxgbe/crypto/t7_kern_tls.c4
-rw-r--r--sys/dev/cxgbe/t4_main.c2
-rw-r--r--sys/dev/hwpmc/hwpmc_intel.c4
-rw-r--r--sys/dev/ichiic/ig4_pci.c12
-rw-r--r--sys/dev/ichsmb/ichsmb_pci.c4
-rw-r--r--sys/dev/ntsync/linux_ntsync.c302
-rw-r--r--sys/dev/ntsync/linux_ntsync.h62
-rw-r--r--sys/dev/ntsync/ntsync.c1420
-rw-r--r--sys/dev/ntsync/ntsync.h66
-rw-r--r--sys/dev/ntsync/ntsyncvar.h119
-rw-r--r--sys/dev/rtwn/usb/rtwn_usb_attach.h1
-rw-r--r--sys/dev/sound/pcm/sound.c47
-rw-r--r--sys/dev/usb/input/ukbd.c16
-rw-r--r--sys/dev/usb/usb_transfer.c2
-rw-r--r--sys/dev/usb/usbdevs1
24 files changed, 4344 insertions, 240 deletions
diff --git a/sys/dev/asmc/asmc.c b/sys/dev/asmc/asmc.c
index 8cd7842d03fd..9b7adb61e6de 100644
--- a/sys/dev/asmc/asmc.c
+++ b/sys/dev/asmc/asmc.c
@@ -57,6 +57,7 @@
#include <dev/acpica/acpivar.h>
#include <dev/asmc/asmcvar.h>
+#include <dev/asmc/asmcmmio.h>
#include <dev/backlight/backlight.h>
#include "backlight_if.h"
@@ -426,17 +427,40 @@ asmc_attach(device_t dev)
struct sysctl_ctx_list *sysctlctx;
struct sysctl_oid *sysctlnode;
- sc->sc_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
- &sc->sc_rid_port, RF_ACTIVE);
- if (sc->sc_ioport == NULL) {
- device_printf(dev, "unable to allocate IO port\n");
- return (ENOMEM);
+ /*
+ * Try MMIO first (T2 Macs expose SMC via memory-mapped I/O).
+ * Fall back to standard I/O port if MMIO is not available.
+ */
+ sc->sc_rid_mem = 0;
+ sc->sc_iomem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
+ &sc->sc_rid_mem, RF_ACTIVE);
+ if (sc->sc_iomem != NULL) {
+ if (asmc_mmio_probe(dev) == 0) {
+ sc->sc_is_mmio = 1;
+ device_printf(dev, "using MMIO backend (T2)\n");
+ } else {
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ sc->sc_rid_mem, sc->sc_iomem);
+ sc->sc_iomem = NULL;
+ }
+ }
+
+ if (!sc->sc_is_mmio) {
+ sc->sc_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+ &sc->sc_rid_port, RF_ACTIVE);
+ if (sc->sc_ioport == NULL) {
+ device_printf(dev, "unable to allocate IO port\n");
+ ret = ENOMEM;
+ goto err;
+ }
}
sysctlctx = device_get_sysctl_ctx(dev);
sysctlnode = device_get_sysctl_tree(dev);
- mtx_init(&sc->sc_mtx, "asmc", NULL, MTX_SPIN);
+ /* Mutex may already be initialized by asmc_mmio_probe() */
+ if (!mtx_initialized(&sc->sc_mtx))
+ mtx_init(&sc->sc_mtx, "asmc", NULL, MTX_SPIN);
/* Read SMC revision, key count, fan count */
ret = asmc_init(dev);
@@ -615,6 +639,18 @@ asmc_attach(device_t dev)
"SMC key type (4 chars)");
#endif
+ /*
+ * Battery charge limit (T2 Macs).
+ */
+ if (sc->sc_is_t2 &&
+ asmc_key_getinfo(dev, ASMC_KEY_BCLM, NULL, NULL) == 0) {
+ SYSCTL_ADD_PROC(sysctlctx,
+ SYSCTL_CHILDREN(sysctlnode), OID_AUTO, "battery_charge_limit",
+ CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
+ dev, 0, asmc_bclm_sysctl, "I",
+ "Battery charge limit (0-100)");
+ }
+
if (!sc->sc_has_sms)
goto nosms;
@@ -736,6 +772,7 @@ asmc_detach(device_t dev)
sc->sc_ioport);
sc->sc_ioport = NULL;
}
+ asmc_mmio_detach(dev, sc);
if (mtx_initialized(&sc->sc_mtx)) {
mtx_destroy(&sc->sc_mtx);
}
@@ -788,10 +825,25 @@ asmc_init(device_t dev)
sysctlctx = device_get_sysctl_ctx(dev);
error = asmc_key_read(dev, ASMC_KEY_REV, buf, 6);
- if (error != 0)
- goto out;
- device_printf(dev, "SMC revision: %x.%x%x%x\n", buf[0], buf[1], buf[2],
- ntohs(*(uint16_t *)buf + 4));
+ if (error != 0) {
+ /*
+ * Could not read REV key; T2 Macs may not have it.
+ * Use #KEY as a liveness check instead.
+ */
+ if (sc->sc_is_t2) {
+ error = asmc_key_read(dev, ASMC_NKEYS, buf, 4);
+ if (error != 0)
+ goto out;
+ device_printf(dev, "T2 SMC: %d keys\n",
+ be32dec(buf));
+ } else {
+ goto out;
+ }
+ } else {
+ device_printf(dev, "SMC revision: %x.%x%x%x\n",
+ buf[0], buf[1], buf[2],
+ ntohs(*(uint16_t *)buf + 4));
+ }
/* Auto power-on after AC power loss (AUPO). */
if (asmc_key_read(dev, ASMC_KEY_AUPO, buf, 1) == 0) {
@@ -1041,8 +1093,11 @@ asmc_command(device_t dev, uint8_t command)
static int
asmc_key_read(device_t dev, const char *key, uint8_t *buf, uint8_t len)
{
- int i, error = 1, try = 0;
struct asmc_softc *sc = device_get_softc(dev);
+ int i, error = 1, try = 0;
+
+ if (sc->sc_is_mmio)
+ return (asmc_mmio_key_read(dev, key, buf, len));
mtx_lock_spin(&sc->sc_mtx);
@@ -1180,6 +1235,9 @@ asmc_key_getinfo(device_t dev, const char *key, uint8_t *len, char *type)
uint8_t info[ASMC_KEYINFO_RESPLEN];
int i, error = -1, try = 0;
+ if (sc->sc_is_mmio)
+ return (asmc_mmio_key_getinfo(dev, key, len, type));
+
mtx_lock_spin(&sc->sc_mtx);
begin:
@@ -1715,6 +1773,14 @@ asmc_key_dump_by_index(device_t dev, int index, char *key_out,
int error = ENXIO, try = 0;
int i;
+ if (sc->sc_is_mmio) {
+ error = asmc_mmio_key_getbyindex(dev, index, key_out);
+ if (error != 0)
+ return (error);
+ return (asmc_mmio_key_getinfo(dev, key_out, len_out,
+ type_out));
+ }
+
mtx_lock_spin(&sc->sc_mtx);
index_buf[0] = (index >> 24) & 0xff;
@@ -1808,8 +1874,11 @@ asmc_key_search(device_t dev, const char *prefix, unsigned int *idx)
static int
asmc_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len)
{
- int i, error = -1, try = 0;
struct asmc_softc *sc = device_get_softc(dev);
+ int i, error = -1, try = 0;
+
+ if (sc->sc_is_mmio)
+ return (asmc_mmio_key_write(dev, key, buf, len));
mtx_lock_spin(&sc->sc_mtx);
@@ -1865,14 +1934,30 @@ asmc_fan_count(device_t dev)
static int
asmc_fan_getvalue(device_t dev, const char *key, int fan)
{
+ struct asmc_softc *sc = device_get_softc(dev);
int speed;
- uint8_t buf[2];
+ uint8_t buf[4];
char fankey[5];
+ char type[ASMC_TYPELEN + 1];
snprintf(fankey, sizeof(fankey), key, fan);
- if (asmc_key_read(dev, fankey, buf, sizeof(buf)) != 0)
- return (-1);
- speed = (buf[0] << 6) | (buf[1] >> 2);
+
+ /*
+ * T2 Macs use IEEE 754 float ("flt ") for fan speeds,
+ * stored little-endian in the MMIO data register.
+ * Standard Macs use s14.2 fixed-point ("fpe2", 2 bytes).
+ */
+ if (sc->sc_is_t2 &&
+ asmc_key_getinfo(dev, fankey, NULL, type) == 0 &&
+ strncmp(type, "flt ", 4) == 0) {
+ if (asmc_key_read(dev, fankey, buf, 4) != 0)
+ return (-1);
+ speed = (int)asmc_float_to_u32(le32dec(buf));
+ } else {
+ if (asmc_key_read(dev, fankey, buf, 2) != 0)
+ return (-1);
+ speed = (buf[0] << 6) | (buf[1] >> 2);
+ }
return (speed);
}
@@ -1895,17 +1980,30 @@ asmc_fan_getstring(device_t dev, const char *key, int fan, uint8_t *buf,
static int
asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed)
{
- uint8_t buf[2];
+ struct asmc_softc *sc = device_get_softc(dev);
+ uint8_t buf[4];
char fankey[5];
-
- speed *= 4;
-
- buf[0] = speed >> 8;
- buf[1] = speed;
+ char type[ASMC_TYPELEN + 1];
snprintf(fankey, sizeof(fankey), key, fan);
- if (asmc_key_write(dev, fankey, buf, sizeof(buf)) < 0)
- return (-1);
+
+ if (sc->sc_is_t2 &&
+ asmc_key_getinfo(dev, fankey, NULL, type) == 0 &&
+ strncmp(type, "flt ", 4) == 0) {
+ uint32_t fval;
+ speed = MAX(speed, 0);
+ speed = MIN(speed, 65535);
+ fval = asmc_u32_to_float((uint32_t)speed);
+ le32enc(buf, fval);
+ if (asmc_key_write(dev, fankey, buf, 4) != 0)
+ return (-1);
+ } else {
+ speed *= 4;
+ buf[0] = speed >> 8;
+ buf[1] = speed;
+ if (asmc_key_write(dev, fankey, buf, 2) != 0)
+ return (-1);
+ }
return (0);
}
@@ -2016,11 +2114,35 @@ static int
asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS)
{
device_t dev = (device_t)arg1;
+ struct asmc_softc *sc = device_get_softc(dev);
int fan = arg2;
int error;
int32_t v;
uint8_t buf[2];
uint16_t val;
+ char fmkey[5];
+
+ /*
+ * T2 Macs use per-fan F%dMd keys (1 byte each).
+ * Standard Macs use FS! bitmask (2 bytes).
+ */
+ snprintf(fmkey, sizeof(fmkey), ASMC_KEY_FANMANUAL_T2, fan);
+ if (sc->sc_is_t2 &&
+ asmc_key_getinfo(dev, fmkey, NULL, NULL) == 0) {
+ error = asmc_key_read(dev, fmkey, buf, 1);
+ if (error != 0)
+ return (error);
+ v = buf[0] ? 1 : 0;
+
+ error = sysctl_handle_int(oidp, &v, 0, req);
+ if (error == 0 && req->newptr != NULL) {
+ if (v != 0 && v != 1)
+ return (EINVAL);
+ buf[0] = (uint8_t)v;
+ error = asmc_key_write(dev, fmkey, buf, 1);
+ }
+ return (error);
+ }
/* Read current FS! bitmask (asmc_key_read locks internally) */
error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, sizeof(buf));
diff --git a/sys/dev/asmc/asmcmmio.c b/sys/dev/asmc/asmcmmio.c
new file mode 100644
index 000000000000..016c50f6170f
--- /dev/null
+++ b/sys/dev/asmc/asmcmmio.c
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2026 Abdelkader Boudih <freebsd@seuros.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+/*
+ * MMIO backend for Apple SMC (T2 and later Macs).
+ *
+ * T2 Macs expose the SMC via memory-mapped registers instead of I/O ports.
+ * Protocol: clear status, write key/cmd, poll for ready, read result.
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/module.h>
+#include <sys/rman.h>
+#include <sys/sysctl.h>
+#include <sys/systm.h>
+#include <sys/taskqueue.h>
+
+#include <machine/bus.h>
+
+#include <dev/asmc/asmcvar.h>
+#include <dev/asmc/asmcmmio.h>
+
+/*
+ * Wait for MMIO status register bit 5 (ready) with exponential backoff.
+ * Caller must hold sc_mtx.
+ */
+static int
+asmc_mmio_wait(device_t dev)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+ int i;
+ uint8_t status;
+ int delay_us = 10;
+
+ for (i = 0; i < ASMC_MMIO_MAX_WAIT; i++) {
+ status = bus_read_1(sc->sc_iomem, ASMC_MMIO_STATUS);
+ if (status & ASMC_MMIO_STATUS_READY)
+ return (0);
+ DELAY(delay_us);
+ if (delay_us < 3200)
+ delay_us *= 2;
+ }
+
+ return (ETIMEDOUT);
+}
+
+int
+asmc_mmio_key_read(device_t dev, const char *key, uint8_t *buf, uint8_t len)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+ uint32_t key_int;
+ int error, i;
+ uint8_t cmd_result, rlen;
+
+ if (len > ASMC_MAXVAL)
+ return (EINVAL);
+
+ mtx_lock_spin(&sc->sc_mtx);
+
+ /* Clear status if non-zero */
+ if (bus_read_1(sc->sc_iomem, ASMC_MMIO_STATUS))
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_STATUS, 0);
+
+ /* Write key name as raw 4 bytes */
+ memcpy(&key_int, key, 4);
+ bus_write_4(sc->sc_iomem, ASMC_MMIO_KEY_NAME, key_int);
+
+ /* Write SMC ID (always 0) and command */
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_SMC_ID, 0);
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_CMD, ASMC_CMDREAD);
+
+ /* Wait for ready */
+ error = asmc_mmio_wait(dev);
+ if (error != 0) {
+ uint8_t st = bus_read_1(sc->sc_iomem, ASMC_MMIO_STATUS);
+ uint8_t cm = bus_read_1(sc->sc_iomem, ASMC_MMIO_CMD);
+ mtx_unlock_spin(&sc->sc_mtx);
+ device_printf(dev,
+ "%s: timeout key %.4s status=0x%02x cmd=0x%02x\n",
+ __func__, key, st, cm);
+ return (error);
+ }
+
+ /* Check command result (0 = success, 0x84 = key not found) */
+ cmd_result = bus_read_1(sc->sc_iomem, ASMC_MMIO_CMD);
+ if (cmd_result != 0) {
+ mtx_unlock_spin(&sc->sc_mtx);
+ device_printf(dev,
+ "%s: key %.4s cmd error 0x%02x\n",
+ __func__, key, cmd_result);
+ return (EIO);
+ }
+
+ /* Read data length and data bytes; zero-fill remainder */
+ rlen = bus_read_1(sc->sc_iomem, ASMC_MMIO_DATA_LEN);
+ rlen = MIN(rlen, len);
+ for (i = rlen; i < len; i++)
+ buf[i] = 0;
+ for (i = 0; i < rlen; i++)
+ buf[i] = bus_read_1(sc->sc_iomem, ASMC_MMIO_DATA + i);
+
+ mtx_unlock_spin(&sc->sc_mtx);
+ return (0);
+}
+
+int
+asmc_mmio_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+ uint32_t key_int;
+ int error, i;
+ uint8_t cmd_result;
+
+ if (len > ASMC_MAXVAL)
+ return (EINVAL);
+
+ mtx_lock_spin(&sc->sc_mtx);
+
+ /* Clear status */
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_STATUS, 0);
+
+ /* Write data bytes first */
+ for (i = 0; i < len; i++)
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_DATA + i, buf[i]);
+
+ /* Write key name as raw 4 bytes */
+ memcpy(&key_int, key, 4);
+ bus_write_4(sc->sc_iomem, ASMC_MMIO_KEY_NAME, key_int);
+
+ /* Write length, SMC ID, command */
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_DATA_LEN, len);
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_SMC_ID, 0);
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_CMD, ASMC_CMDWRITE);
+
+ /* Wait for ready */
+ error = asmc_mmio_wait(dev);
+ if (error != 0) {
+ mtx_unlock_spin(&sc->sc_mtx);
+ device_printf(dev, "%s: timeout writing key %.4s\n",
+ __func__, key);
+ return (error);
+ }
+
+ cmd_result = bus_read_1(sc->sc_iomem, ASMC_MMIO_CMD);
+ mtx_unlock_spin(&sc->sc_mtx);
+
+ return (cmd_result == 0 ? 0 : EIO);
+}
+
+int
+asmc_mmio_key_getinfo(device_t dev, const char *key, uint8_t *len, char *type)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+ uint32_t key_int;
+ int error, i;
+ uint8_t cmd_result;
+
+ mtx_lock_spin(&sc->sc_mtx);
+
+ /* Clear status */
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_STATUS, 0);
+
+ /* Write key name as raw 4 bytes */
+ memcpy(&key_int, key, 4);
+ bus_write_4(sc->sc_iomem, ASMC_MMIO_KEY_NAME, key_int);
+
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_SMC_ID, 0);
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_CMD, ASMC_CMDGETINFO);
+
+ error = asmc_mmio_wait(dev);
+ if (error != 0) {
+ mtx_unlock_spin(&sc->sc_mtx);
+ return (error);
+ }
+
+ cmd_result = bus_read_1(sc->sc_iomem, ASMC_MMIO_CMD);
+ if (cmd_result != 0) {
+ mtx_unlock_spin(&sc->sc_mtx);
+ return (EIO);
+ }
+
+ /*
+ * GETINFO response layout (MMIO):
+ * data[0..3] = type code (4 chars)
+ * data[4] = reserved
+ * data[5] = data length
+ * data[6] = flags/attributes
+ */
+ if (type != NULL) {
+ for (i = 0; i < ASMC_TYPELEN; i++)
+ type[i] = bus_read_1(sc->sc_iomem,
+ ASMC_MMIO_DATA + i);
+ type[ASMC_TYPELEN] = '\0';
+ }
+ if (len != NULL)
+ *len = bus_read_1(sc->sc_iomem, ASMC_MMIO_DATA + 5);
+
+ mtx_unlock_spin(&sc->sc_mtx);
+ return (0);
+}
+
+int
+asmc_mmio_key_getbyindex(device_t dev, int index, char *key)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+ uint32_t idx_val;
+ int error, i;
+ uint8_t cmd_result;
+
+ mtx_lock_spin(&sc->sc_mtx);
+
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_STATUS, 0);
+
+ /* Write index as big-endian 4 bytes to key name register */
+ idx_val = htobe32(index);
+ bus_write_4(sc->sc_iomem, ASMC_MMIO_KEY_NAME, idx_val);
+
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_SMC_ID, 0);
+ bus_write_1(sc->sc_iomem, ASMC_MMIO_CMD, ASMC_CMDGETBYINDEX);
+
+ error = asmc_mmio_wait(dev);
+ if (error != 0) {
+ mtx_unlock_spin(&sc->sc_mtx);
+ return (error);
+ }
+
+ cmd_result = bus_read_1(sc->sc_iomem, ASMC_MMIO_CMD);
+ if (cmd_result != 0) {
+ mtx_unlock_spin(&sc->sc_mtx);
+ return (EIO);
+ }
+
+ /* Result: 4-byte key name in DATA */
+ for (i = 0; i < ASMC_KEYLEN; i++)
+ key[i] = bus_read_1(sc->sc_iomem, ASMC_MMIO_DATA + i);
+ key[ASMC_KEYLEN] = '\0';
+
+ mtx_unlock_spin(&sc->sc_mtx);
+ return (0);
+}
+
+/*
+ * Validate MMIO and detect T2.
+ * Check that status register is accessible and LDKN firmware version >= 2.
+ */
+int
+asmc_mmio_probe(device_t dev)
+{
+ struct asmc_softc *sc = device_get_softc(dev);
+ rman_res_t size;
+ uint8_t status, ldkn;
+ int error;
+
+ size = rman_get_size(sc->sc_iomem);
+ if (size < ASMC_MMIO_MIN_SIZE) {
+ device_printf(dev, "MMIO region too small (%jd < %d)\n",
+ (intmax_t)size, ASMC_MMIO_MIN_SIZE);
+ return (ENXIO);
+ }
+
+ /* Check status register isn't stuck at 0xFF */
+ status = bus_read_1(sc->sc_iomem, ASMC_MMIO_STATUS);
+ if (status == 0xFF) {
+ device_printf(dev, "MMIO status register reads 0xFF\n");
+ return (ENXIO);
+ }
+
+ /*
+ * We need the mutex initialized before calling mmio_key_read,
+ * but attach hasn't done it yet. Initialize early.
+ */
+ if (!mtx_initialized(&sc->sc_mtx))
+ mtx_init(&sc->sc_mtx, "asmc", NULL, MTX_SPIN);
+
+ /* Read LDKN (firmware version) -- must be >= 2 for MMIO */
+ error = asmc_mmio_key_read(dev, ASMC_KEY_LDKN, &ldkn, 1);
+ if (error != 0) {
+ device_printf(dev, "MMIO: failed to read LDKN key\n");
+ return (ENXIO);
+ }
+
+ if (ldkn < 2) {
+ device_printf(dev, "MMIO: LDKN=%d (need >= 2)\n", ldkn);
+ return (ENXIO);
+ }
+
+ device_printf(dev, "MMIO: LDKN=%d, T2 SMC detected\n", ldkn);
+ sc->sc_is_t2 = 1;
+
+ return (0);
+}
+
+void
+asmc_mmio_detach(device_t dev, struct asmc_softc *sc)
+{
+
+ if (sc->sc_iomem != NULL) {
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid_mem,
+ sc->sc_iomem);
+ sc->sc_iomem = NULL;
+ }
+ sc->sc_is_mmio = 0;
+ sc->sc_is_t2 = 0;
+}
+
+/*
+ * Convert IEEE 754 float (as u32) to unsigned integer.
+ * Kernel soft-float: extract integer part only.
+ * Used for T2 fan RPM values (always positive, reasonable range).
+ */
+uint32_t
+asmc_float_to_u32(uint32_t d)
+{
+ int32_t exp;
+ uint32_t fr;
+
+ /* Negative or zero */
+ if (d == 0 || (d >> 31) != 0)
+ return (0);
+
+ exp = (int32_t)((d >> 23) & 0xff) - 0x7f;
+ fr = d & 0x7fffff; /* 23-bit mantissa */
+
+ if (exp < 0)
+ return (0);
+ if (exp > 23) {
+ if (exp > 30)
+ return (0xffffffffu);
+ return ((1u << exp) | (fr << (exp - 23)));
+ }
+ /* Normal case: 0 <= exp <= 23 */
+ return ((1u << exp) + (fr >> (23 - exp)));
+}
+
+/*
+ * Convert unsigned integer to IEEE 754 float (as u32).
+ * Only handles values in fan RPM range (0-65535).
+ */
+uint32_t
+asmc_u32_to_float(uint32_t d)
+{
+ uint32_t dc, bc, exp;
+
+ if (d == 0)
+ return (0);
+
+ /* Find highest set bit position */
+ dc = d;
+ bc = 0;
+ while (dc >>= 1)
+ ++bc;
+
+ bc = MIN(bc, 30);
+
+ exp = 0x7f + bc;
+
+ /*
+ * Mantissa: strip the implicit leading 1-bit and place
+ * remaining bits into the 23-bit mantissa field.
+ */
+ if (bc >= 23)
+ return ((exp << 23) | ((d >> (bc - 23)) & 0x7fffff));
+ else
+ return ((exp << 23) | ((d << (23 - bc)) & 0x7fffff));
+}
+
+/*
+ * Battery charge limit sysctl (T2 Macs).
+ * BCLM key: 1 byte, 0-100 (percentage).
+ */
+int
+asmc_bclm_sysctl(SYSCTL_HANDLER_ARGS)
+{
+ device_t dev = (device_t)arg1;
+ uint8_t bclm;
+ int val, error;
+
+ error = asmc_mmio_key_read(dev, ASMC_KEY_BCLM, &bclm, 1);
+ if (error != 0)
+ return (EIO);
+
+ val = (int)bclm;
+ error = sysctl_handle_int(oidp, &val, 0, req);
+ if (error != 0 || req->newptr == NULL)
+ return (error);
+
+ if (val < 0 || val > 100)
+ return (EINVAL);
+
+ bclm = (uint8_t)val;
+ error = asmc_mmio_key_write(dev, ASMC_KEY_BCLM, &bclm, 1);
+
+ return (error != 0 ? EIO : 0);
+}
diff --git a/sys/dev/asmc/asmcmmio.h b/sys/dev/asmc/asmcmmio.h
new file mode 100644
index 000000000000..51e81707ece1
--- /dev/null
+++ b/sys/dev/asmc/asmcmmio.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2026 Abdelkader Boudih <freebsd@seuros.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef _DEV_ASMC_ASMCMMIO_H_
+#define _DEV_ASMC_ASMCMMIO_H_
+
+struct asmc_softc;
+
+/*
+ * MMIO register offsets.
+ */
+#define ASMC_MMIO_DATA 0x0000
+#define ASMC_MMIO_KEY_NAME 0x0078
+#define ASMC_MMIO_DATA_LEN 0x007D
+#define ASMC_MMIO_SMC_ID 0x007E
+#define ASMC_MMIO_CMD 0x007F
+#define ASMC_MMIO_STATUS 0x4005
+#define ASMC_MMIO_MIN_SIZE 0x4006
+#define ASMC_MMIO_STATUS_READY 0x20 /* Bit 5 */
+#define ASMC_MMIO_MAX_WAIT 24
+
+/*
+ * T2-specific keys.
+ */
+#define ASMC_KEY_LDKN "LDKN" /* RO; 1 byte, firmware version */
+#define ASMC_KEY_BCLM "BCLM" /* RW; 1 byte, battery charge limit 0-100 */
+#define ASMC_KEY_FANMANUAL_T2 "F%dMd" /* RW; 1 byte per fan (T2) */
+
+/*
+ * MMIO backend functions.
+ */
+int asmc_mmio_probe(device_t dev);
+void asmc_mmio_detach(device_t dev, struct asmc_softc *sc);
+int asmc_mmio_key_read(device_t dev, const char *key,
+ uint8_t *buf, uint8_t len);
+int asmc_mmio_key_write(device_t dev, const char *key,
+ uint8_t *buf, uint8_t len);
+int asmc_mmio_key_getinfo(device_t dev, const char *key,
+ uint8_t *len, char *type);
+int asmc_mmio_key_getbyindex(device_t dev, int index, char *key);
+
+/*
+ * IEEE 754 float <-> uint32 conversion for T2 fan RPM values.
+ */
+uint32_t asmc_float_to_u32(uint32_t d);
+uint32_t asmc_u32_to_float(uint32_t d);
+
+/*
+ * T2-specific sysctls.
+ */
+int asmc_bclm_sysctl(SYSCTL_HANDLER_ARGS);
+
+#endif /* _DEV_ASMC_ASMCMMIO_H_ */
diff --git a/sys/dev/asmc/asmcvar.h b/sys/dev/asmc/asmcvar.h
index 6388fc78fb69..bc0c624eb7a2 100644
--- a/sys/dev/asmc/asmcvar.h
+++ b/sys/dev/asmc/asmcvar.h
@@ -53,6 +53,11 @@ struct asmc_softc {
struct resource *sc_ioport;
struct resource *sc_irq;
void *sc_cookie;
+ /* MMIO backend (T2 Macs) */
+ int sc_rid_mem;
+ struct resource *sc_iomem;
+ int sc_is_mmio;
+ int sc_is_t2; /* T2 fan float + per-fan manual */
int sc_sms_intrtype;
struct taskqueue *sc_sms_tq;
struct task sc_sms_task;
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_sriov.c b/sys/dev/bnxt/bnxt_en/bnxt_sriov.c
index 270c18165fb7..071feffbadfd 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_sriov.c
+++ b/sys/dev/bnxt/bnxt_en/bnxt_sriov.c
@@ -7,6 +7,8 @@
#include "bnxt_hwrm.h"
#include "bnxt_sriov.h"
+#ifdef PCI_IOV
+
static int
bnxt_set_vf_admin_mac(struct bnxt_softc *softc, struct bnxt_vf_info *vf,
const uint8_t *mac)
@@ -973,6 +975,43 @@ void bnxt_sriov_attach(struct bnxt_softc *softc)
device_printf(dev, "Failed to initialize SR-IOV (error=%d)\n", rc);
}
+#else
+
+void
+bnxt_sriov_attach(struct bnxt_softc *softc __unused)
+{
+}
+
+int
+bnxt_cfg_hw_sriov(struct bnxt_softc *softc __unused,
+ uint16_t *num_vfs __unused, bool reset __unused)
+{
+ return (0);
+}
+
+int
+bnxt_approve_mac(struct bnxt_softc *sc __unused)
+{
+ return (0);
+}
+
+void
+bnxt_hwrm_exec_fwd_req(struct bnxt_softc *softc __unused)
+{
+}
+
+bool
+bnxt_promisc_ok(struct bnxt_softc *softc __unused)
+{
+ return (true);
+}
+
+void
+bnxt_update_vf_mac(struct bnxt_softc *sc __unused)
+{
+}
+#endif
+
void bnxt_reenable_sriov(struct bnxt_softc *bp)
{
if (BNXT_PF(bp)) {
diff --git a/sys/dev/bnxt/bnxt_en/bnxt_sriov.h b/sys/dev/bnxt/bnxt_en/bnxt_sriov.h
index 176f54af0aa8..24ea11f29b83 100644
--- a/sys/dev/bnxt/bnxt_en/bnxt_sriov.h
+++ b/sys/dev/bnxt/bnxt_en/bnxt_sriov.h
@@ -8,10 +8,6 @@
#include "opt_global.h"
#include "bnxt.h"
-#ifndef PCI_IOV
-#define PCI_IOV 1
-#endif
-
/* macro definations */
#define BNXT_MAX_VFS 4
diff --git a/sys/dev/bnxt/bnxt_en/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c
index 6618016f3932..6d82302615e1 100644
--- a/sys/dev/bnxt/bnxt_en/if_bnxt.c
+++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c
@@ -2875,11 +2875,9 @@ bnxt_attach_post(if_ctx_t ctx)
bnxt_dcb_init(softc);
bnxt_rdma_aux_device_init(softc);
-#if PCI_IOV
/* SR-IOV attach */
if (BNXT_PF(softc) && BNXT_CHIP_P5_PLUS(softc))
bnxt_sriov_attach(softc);
-#endif
failed:
return rc;
diff --git a/sys/dev/cxgbe/adapter.h b/sys/dev/cxgbe/adapter.h
index 24a482b74dfb..8c5cf052b689 100644
--- a/sys/dev/cxgbe/adapter.h
+++ b/sys/dev/cxgbe/adapter.h
@@ -194,6 +194,7 @@ enum {
IHF_CLR_ALL_SET = (1 << 5), /* Clear all set bits */
IHF_CLR_ALL_UNIGNORED = (1 << 6), /* Clear all unignored bits */
IHF_RUN_ALL_ACTIONS = (1 << 7), /* As if all cause are set */
+ IHF_CLR_DELAYED = (1 << 9), /* Cleared in a delayed call */
};
#define IS_DETACHING(vi) ((vi)->flags & VI_DETACHING)
diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c
index f4eef54e5c6b..1386ae1767fd 100644
--- a/sys/dev/cxgbe/common/t4_hw.c
+++ b/sys/dev/cxgbe/common/t4_hw.c
@@ -4794,6 +4794,27 @@ struct intr_info {
const struct intr_action *actions;
};
+/* Helper to clear interrupts that have IHF_CLR_DELAYED. */
+static void
+clear_int_cause_reg(struct adapter *sc, const struct intr_info *ii, int flags)
+{
+ u32 cause, ucause;
+
+ cause = ucause = t4_read_reg(sc, ii->cause_reg);
+ if (cause == 0)
+ return;
+ flags |= ii->flags;
+ if (flags & IHF_IGNORE_IF_DISABLED)
+ ucause &= t4_read_reg(sc, ii->enable_reg);
+ if (flags & IHF_CLR_ALL_SET) {
+ t4_write_reg(sc, ii->cause_reg, cause);
+ (void)t4_read_reg(sc, ii->cause_reg);
+ } else if (ucause != 0 && flags & IHF_CLR_ALL_UNIGNORED) {
+ t4_write_reg(sc, ii->cause_reg, ucause);
+ (void)t4_read_reg(sc, ii->cause_reg);
+ }
+}
+
static inline char
intr_alert_char(u32 cause, u32 enable, u32 fatal)
{
@@ -4869,8 +4890,8 @@ t4_handle_intr(struct adapter *sc, const struct intr_info *ii, uint32_t acause,
}
}
- /* clear */
- if (cause != 0) {
+ /* Clear here unless delayed clear is requested. */
+ if (cause != 0 && (flags & IHF_CLR_DELAYED) == 0) {
if (flags & IHF_CLR_ALL_SET) {
t4_write_reg(sc, ii->cause_reg, cause);
(void)t4_read_reg(sc, ii->cause_reg);
@@ -5003,22 +5024,63 @@ static bool pcie_intr_handler(struct adapter *adap, int arg, int flags)
.details = NULL,
.actions = NULL,
};
+ static const struct intr_details pcie_intr_cause_ext_details[] = {
+ { F_IPFORMQPERR, "PCIe IP FormQ Buffer PERR" },
+ { F_IPFORMQCERR, "PCIe IP FormQ Buffer CERR" },
+ { F_TRGT1GRPCERR, "TRGT1 Group FIFOs CERR" },
+ { F_IPSOTCERR, "PCIe IP SOT Buffer SRAM CERR" },
+ { F_IPRETRYCERR, "PCIe IP Replay Buffer CERR" },
+ { F_IPRXDATAGRPCERR, "PCIe IP Rx Data Group SRAMs CERR" },
+ { F_IPRXHDRGRPCERR, "PCIe IP Rx Header Group SRAMs CERR" },
+ { F_A0ARBRSPORDFIFOPERR, "A0 Arbiter Response Order FIFO Parity Error" },
+ { F_HRSPCERR, "Master HMA Channel Response Data SRAM CERR" },
+ { F_HREQRDCERR, "Master HMA Channel Read Request SRAM CERR" },
+ { F_HREQWRCERR, "Master HMA Channel Write Request SRAM CERR" },
+ { F_DRSPCERR, "Master DMA Channel Response Data SRAM CERR" },
+ { F_DREQRDCERR, "Master DMA Channel Read Request SRAM CERR" },
+ { F_DREQWRCERR, "Master DMA Channel Write Request SRAM CERR" },
+ { F_CRSPCERR, "Master CMD Channel Response Data SRAM CERR" },
+ { F_ARSPPERR, "Master ARM Channel Response Data SRAM PERR" },
+ { F_AREQRDPERR, "Master ARM Channel Read Request SRAM PERR" },
+ { F_AREQWRPERR, "Master ARM Channel Write Request SRAM PERR" },
+ { F_PIOREQGRPCERR, "PIO Request Group FIFOs CERR" },
+ { F_ARSPCERR, "Master ARM Channel Response Data SRAM CERR" },
+ { F_AREQRDCERR, "Master ARM Channel Read Request SRAM CERR" },
+ { F_AREQWRCERR, "Master ARM Channel Write Request SRAM CERR" },
+ { F_MARSPPERR, "INIC MA Ctrl and Data Rsp Perr" },
+ { F_INICMAWDATAORDPERR, "INIC Ma Arb Write Ord Data Fifo Perr" },
+ { F_EMUPERR, "CFG EMU SRAM PERR" },
+ { F_ERRSPPERR, "CFG EMU SRAM CERR" },
+ { F_MSTGRPCERR, "Master Data Path and Response Read Queue SRAM CERR" },
+ { 0 }
+ };
struct intr_info pcie_int_cause_ext = {
.name = "PCIE_INT_CAUSE_EXT",
.cause_reg = A_PCIE_INT_CAUSE_EXT,
.enable_reg = A_PCIE_INT_ENABLE_EXT,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = pcie_intr_cause_ext_details,
.actions = NULL,
};
+ static const struct intr_details pcie_intr_cause_x8_details[] = {
+ { F_X8TGTGRPPERR, "x8 TGT Group FIFOs parity error" },
+ { F_X8IPSOTPERR, "PCIe x8 IP SOT Buffer SRAM PERR" },
+ { F_X8IPRETRYPERR, "PCIe x8 IP Replay Buffer PERR" },
+ { F_X8IPRXDATAGRPPERR, "PCIe x8 IP Rx Data Group SRAMs PERR" },
+ { F_X8IPRXHDRGRPPERR, "PCIe x8 IP Rx Header Group SRAMs PERR" },
+ { F_X8IPCORECERR, "x8 IP SOT, Retry, RxData, RxHdr SRAM CERR" },
+ { F_X8MSTGRPPERR, "x8 Master Data Path and Response Read Queue SRAM PERR" },
+ { F_X8MSTGRPCERR, "x8 Master Data Path and Response Read Queue SRAM CERR" },
+ { 0 }
+ };
struct intr_info pcie_int_cause_x8 = {
.name = "PCIE_INT_CAUSE_X8",
.cause_reg = A_PCIE_INT_CAUSE_X8,
.enable_reg = A_PCIE_INT_ENABLE_X8,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = pcie_intr_cause_x8_details,
.actions = NULL,
};
bool fatal = false;
@@ -5050,80 +5112,247 @@ static bool tp_intr_handler(struct adapter *adap, int arg, int flags)
{ F_FLMTXFLSTEMPTY, "TP out of Tx pages" },
{ 0 }
};
- static const struct intr_info tp_intr_info = {
+ static const struct intr_details t7_tp_intr_details[] = {
+ { F_FLMTXFLSTEMPTY, "Offload memory manager Tx free list empty" },
+ { F_TPCERR, "TP modules flagged Correctable Error" },
+ { F_OTHERPERR, "TP Other modules (Core, TM, FLM, MMGR, DB) Parity Error" },
+ { F_TPEING1PERR, "TP-ESide Ingress1 Parity Error" },
+ { F_TPEING0PERR, "TP-ESide Ingress0 Parity Error" },
+ { F_TPEEGPERR, "TP-ESide Egress Parity Error" },
+ { F_TPCPERR, "TP-CSide Parity Error" },
+ { 0 }
+ };
+ struct intr_info tp_intr_info = {
.name = "TP_INT_CAUSE",
.cause_reg = A_TP_INT_CAUSE,
.enable_reg = A_TP_INT_ENABLE,
.fatal = 0x7fffffff,
- .flags = IHF_FATAL_IFF_ENABLED,
- .details = tp_intr_details,
+ .flags = IHF_FATAL_IFF_ENABLED | IHF_CLR_DELAYED,
+ .details = NULL,
.actions = NULL,
};
- static const struct intr_info tp_inic_perr_cause = {
- .name = "TP_INIC_PERR_CAUSE",
- .cause_reg = A_TP_INIC_PERR_CAUSE,
- .enable_reg = A_TP_INIC_PERR_ENABLE,
+ static const struct intr_details tp_cerr_cause_details[] = {
+ { F_TPCEGDATAFIFO, "TPCSide Egress Data FIFO" },
+ { F_TPCLBKDATAFIFO, "TPCSide Loopback Data FIFO" },
+ { F_RSSLKPSRAM, "RSS Lookup SRAM" },
+ { F_SRQSRAM, "SRQ SRAM" },
+ { F_ARPDASRAM, "ARP DA SRAM" },
+ { F_ARPSASRAM, "ARP SA SRAM" },
+ { F_ARPGRESRAM, "ARP GRE SRAM" },
+ { F_ARPIPSECSRAM1, "ARP IPSec SRAM0" },
+ { F_ARPIPSECSRAM0, "ARP IPSec SRAM1" },
+ { 0 }
+ };
+ static const struct intr_info tp_cerr_cause = {
+ .name = "TP_CERR_CAUSE",
+ .cause_reg = A_TP_CERR_CAUSE,
+ .enable_reg = A_TP_CERR_ENABLE,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = tp_cerr_cause_details,
.actions = NULL,
};
+ static const struct intr_details tp_c_perr_details[] = {
+ { F_DMXFIFOOVFL, "Demux FIFO Overflow" },
+ { F_URX2TPCDDPINTF, "ULPRX to TPC DDP Interface and FIFO" },
+ { F_TPCDISPTOKENFIFO, "TPC Dispatch Token FIFO" },
+ { F_TPCDISPCPLFIFO3, "TPC Dispatch CPL FIFO Ch3" },
+ { F_TPCDISPCPLFIFO2, "TPC Dispatch CPL FIFO Ch2" },
+ { F_TPCDISPCPLFIFO1, "TPC Dispatch CPL FIFO Ch1" },
+ { F_TPCDISPCPLFIFO0, "TPC Dispatch CPL FIFO Ch0" },
+ { F_URXPLDINTFCRC3, "ULPRX to TPC Payload Interface CRC Error Ch3" },
+ { F_URXPLDINTFCRC2, "ULPRX to TPC Payload Interface CRC Error Ch2" },
+ { F_URXPLDINTFCRC1, "ULPRX to TPC Payload Interface CRC Error Ch1" },
+ { F_URXPLDINTFCRC0, "ULPRX to TPC Payload Interface CRC Error Ch0" },
+ { F_DMXDBFIFO, "Demux DB FIFO" },
+ { F_DMXDBSRAM, "Demux DB SRAM" },
+ { F_DMXCPLFIFO, "Demux CPL FIFO" },
+ { F_DMXCPLSRAM, "Demux CPL SRAM" },
+ { F_DMXCSUMFIFO, "Demux Checksum FIFO" },
+ { F_DMXLENFIFO, "Demux Length FIFO" },
+ { F_DMXCHECKFIFO, "Demux Check CRC16 FIFO" },
+ { F_DMXWINFIFO, "Demux Winner FIFO" },
+ { F_EGTOKENFIFO, "Egress Token FIFO Parity Error" },
+ { F_EGDATAFIFO, "Egress FIFO Parity Error" },
+ { F_UTX2TPCINTF3, "ULPTX to TPC Interface Parity Error Ch3" },
+ { F_UTX2TPCINTF2, "ULPTX to TPC Interface Parity Error Ch2" },
+ { F_UTX2TPCINTF1, "ULPTX to TPC Interface Parity Error Ch1" },
+ { F_UTX2TPCINTF0, "ULPTX to TPC Interface Parity Error Ch0" },
+ { F_LBKTOKENFIFO, "Loopback Token FIFO Parity Error" },
+ { F_LBKDATAFIFO, "Loopback FIFO Parity Error" },
+ { 0 }
+ };
static const struct intr_info tp_c_perr_cause = {
.name = "TP_C_PERR_CAUSE",
.cause_reg = A_TP_C_PERR_CAUSE,
.enable_reg = A_TP_C_PERR_ENABLE,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = tp_c_perr_details,
.actions = NULL,
};
+ static const struct intr_details tp_e_eg_perr_details[] = {
+ { F_MPSLPBKTOKENFIFO, "MPS Loopback Token FIFO parity error" },
+ { F_MPSMACTOKENFIFO, "MPS MAC Token FIFO parity error" },
+ { F_DISPIPSECFIFO3, "Ch3 Dispatch IPSec FIFO parity error" },
+ { F_DISPTCPFIFO3, "Ch3 Dispatch TCP FIFO parity error" },
+ { F_DISPIPFIFO3, "Ch3 Dispatch IP FIFO parity error" },
+ { F_DISPETHFIFO3, "Ch3 Dispatch ETH FIFO parity error" },
+ { F_DISPGREFIFO3, "Ch3 Dispatch GRE FIFO parity error" },
+ { F_DISPCPL5FIFO3, "Ch3 Dispatch CPL5 FIFO parity error" },
+ { F_DISPIPSECFIFO2, "Ch2 Dispatch IPSec FIFO parity error" },
+ { F_DISPTCPFIFO2, "Ch2 Dispatch TCP FIFO parity error" },
+ { F_DISPIPFIFO2, "Ch2 Dispatch IP FIFO parity error" },
+ { F_DISPETHFIFO2, "Ch2 Dispatch ETH FIFO parity error" },
+ { F_DISPGREFIFO2, "Ch2 Dispatch GRE FIFO parity error" },
+ { F_DISPCPL5FIFO2, "Ch2 Dispatch CPL5 FIFO parity error" },
+ { F_DISPIPSECFIFO1, "Ch1 Dispatch IPSec FIFO parity error" },
+ { F_DISPTCPFIFO1, "Ch1 Dispatch TCP FIFO parity error" },
+ { F_DISPIPFIFO1, "Ch1 Dispatch IP FIFO parity error" },
+ { F_DISPETHFIFO1, "Ch1 Dispatch ETH FIFO parity error" },
+ { F_DISPGREFIFO1, "Ch1 Dispatch GRE FIFO parity error" },
+ { F_DISPCPL5FIFO1, "Ch1 Dispatch CPL5 FIFO parity error" },
+ { F_DISPIPSECFIFO0, "Ch0 Dispatch IPSec FIFO parity error" },
+ { F_DISPTCPFIFO0, "Ch0 Dispatch TCP FIFO parity error" },
+ { F_DISPIPFIFO0, "Ch0 Dispatch IP FIFO parity error" },
+ { F_DISPETHFIFO0, "Ch0 Dispatch ETH FIFO parity error" },
+ { F_DISPGREFIFO0, "Ch0 Dispatch GRE FIFO parity error" },
+ { F_DISPCPL5FIFO0, "Ch0 Dispatch CPL5 FIFO parity error" },
+ { 0 }
+ };
static const struct intr_info tp_e_eg_perr_cause = {
.name = "TP_E_EG_PERR_CAUSE",
.cause_reg = A_TP_E_EG_PERR_CAUSE,
.enable_reg = A_TP_E_EG_PERR_ENABLE,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = tp_e_eg_perr_details,
.actions = NULL,
};
+ static const struct intr_details tp_e_in0_perr_details[] = {
+ { F_DMXISSFIFO, "Demux ISS FIFO parity error" },
+ { F_DMXERRFIFO, "Demux Error FIFO parity error" },
+ { F_DMXATTFIFO, "Demux Attributes FIFO parity error" },
+ { F_DMXTCPFIFO, "Demux TCP Fields FIFO parity error" },
+ { F_DMXMPAFIFO, "Demux MPA FIFO parity error" },
+ { F_DMXOPTFIFO, "Demux TCP Options FIFO parity error" },
+ { F_INGTOKENFIFO, "Demux Ingress Token FIFO parity error" },
+ { F_DMXPLDCHKOVFL1, "Ch1 PLD TxCheck FIFO Overflow" },
+ { F_DMXPLDCHKFIFO1, "Ch1 PLD TxCheck FIFO parity error" },
+ { F_DMXOPTFIFO1, "Ch1 Options buffer parity error" },
+ { F_DMXMPAFIFO1, "Ch1 MPA FIFO parity error" },
+ { F_DMXDBFIFO1, "Ch1 DB FIFO parity error" },
+ { F_DMXATTFIFO1, "Ch1 Attribute FIFO parity error" },
+ { F_DMXISSFIFO1, "Ch1 ISS FIFO parity error" },
+ { F_DMXTCPFIFO1, "Ch1 TCP Fields FIFO parity error" },
+ { F_DMXERRFIFO1, "Ch1 Error FIFO parity error" },
+ { F_MPS2TPINTF1, "Ch1 MPS2TP Interface parity error" },
+ { F_DMXPLDCHKOVFL0, "Ch0 PLD TxCheck FIFO Overflow" },
+ { F_DMXPLDCHKFIFO0, "Ch0 PLD TxCheck FIFO parity error" },
+ { F_DMXOPTFIFO0, "Ch0 Options buffer parity error" },
+ { F_DMXMPAFIFO0, "Ch0 MPA FIFO parity error" },
+ { F_DMXDBFIFO0, "Ch0 DB FIFO parity error" },
+ { F_DMXATTFIFO0, "Ch0 Attribute FIFO parity error" },
+ { F_DMXISSFIFO0, "Ch0 ISS FIFO parity error" },
+ { F_DMXTCPFIFO0, "Ch0 TCP Fields FIFO parity error" },
+ { F_DMXERRFIFO0, "Ch0 Error FIFO parity error" },
+ { F_MPS2TPINTF0, "Ch0 MPS2TP Interface parity error" },
+ { 0 }
+ };
static const struct intr_info tp_e_in0_perr_cause = {
.name = "TP_E_IN0_PERR_CAUSE",
.cause_reg = A_TP_E_IN0_PERR_CAUSE,
.enable_reg = A_TP_E_IN0_PERR_ENABLE,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = tp_e_in0_perr_details,
.actions = NULL,
};
+ static const struct intr_details tp_e_in1_perr_details[] = {
+ { F_DMXPLDCHKOVFL3, "Ch3 PLD TxCheck FIFO Overflow" },
+ { F_DMXPLDCHKFIFO3, "Ch3 PLD TxCheck FIFO parity error" },
+ { F_DMXOPTFIFO3, "Ch3 Options buffer parity error" },
+ { F_DMXMPAFIFO3, "Ch3 MPA FIFO parity error" },
+ { F_DMXDBFIFO3, "Ch3 DB FIFO parity error" },
+ { F_DMXATTFIFO3, "Ch3 Attribute FIFO parity error" },
+ { F_DMXISSFIFO3, "Ch3 ISS FIFO parity error" },
+ { F_DMXTCPFIFO3, "Ch3 TCP Fields FIFO parity error" },
+ { F_DMXERRFIFO3, "Ch3 Error FIFO parity error" },
+ { F_MPS2TPINTF3, "Ch3 MPS2TP Interface parity error" },
+ { F_DMXPLDCHKOVFL2, "Ch2 PLD TxCheck FIFO Overflow" },
+ { F_DMXPLDCHKFIFO2, "Ch2 PLD TxCheck FIFO parity error" },
+ { F_DMXOPTFIFO2, "Ch2 Options buffer parity error" },
+ { F_DMXMPAFIFO2, "Ch2 MPA FIFO parity error" },
+ { F_DMXDBFIFO2, "Ch2 DB FIFO parity error" },
+ { F_DMXATTFIFO2, "Ch2 Attribute FIFO parity error" },
+ { F_DMXISSFIFO2, "Ch2 ISS FIFO parity error" },
+ { F_DMXTCPFIFO2, "Ch2 TCP Fields FIFO parity error" },
+ { F_DMXERRFIFO2, "Ch2 Error FIFO parity error" },
+ { F_MPS2TPINTF2, "Ch2 MPS2TP Interface parity error" },
+ { 0 }
+ };
static const struct intr_info tp_e_in1_perr_cause = {
.name = "TP_E_IN1_PERR_CAUSE",
.cause_reg = A_TP_E_IN1_PERR_CAUSE,
.enable_reg = A_TP_E_IN1_PERR_ENABLE,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = tp_e_in1_perr_details,
.actions = NULL,
};
+ static const struct intr_details tp_other_perr_details[] = {
+ { F_DMARBTPERR, "DMARBT MA Rsp Interface parity Error" },
+ { F_MMGRCACHEDATASRAM, "TP MMGR Cache Data SRAM" },
+ { F_MMGRCACHETAGFIFO, "TP MMGR Cache Tag FIFO" },
+ { F_DBL2TLUTPERR, "TP DB Lookup Table" },
+ { F_DBTXTIDPERR, "TP DB FIFOs" },
+ { F_DBEXTPERR, "TP DB Extended Opcode FIFO" },
+ { F_DBOPPERR, "TP DB Opcode FIFO" },
+ { F_TMCACHEPERR, "TP TM Cache SRAM" },
+ { F_TPPROTOSRAM, "TP Protocol SRAM" },
+ { F_HSPSRAM, "HighSpeed SRAM" },
+ { F_RATEGRPSRAM, "Rate Group SRAM" },
+ { F_TXFBSEQFIFO, "Tx Feedback Sequence Number FIFO" },
+ { F_CMDATASRAM, "Cache Data SRAM" },
+ { F_CMTAGFIFO, "Cache Tag FIFO" },
+ { F_RFCOPFIFO, "RCF Opcode FIFO" },
+ { F_DELINVFIFO, "Delete Invalid FIFO" },
+ { F_RSSCFGSRAM, "RSS Config or Round-Robin SRAM" },
+ { F_RSSKEYSRAM, "RSS Key SRAM" },
+ { F_RSSLKPSRAM, "RSS Lookup SRAM" },
+ { F_SRQSRAM, "SRQ SRAM" },
+ { F_ARPDASRAM, "ARP DA SRAM" },
+ { F_ARPSASRAM, "ARP SA SRAM" },
+ { F_ARPGRESRAM, "ARP GRE SRAM" },
+ { F_ARPIPSECSRAM1, "ARP IPSec SRAM0" },
+ { F_ARPIPSECSRAM0, "ARP IPSec SRAM1" },
+ { 0 }
+ };
static const struct intr_info tp_o_perr_cause = {
.name = "TP_O_PERR_CAUSE",
.cause_reg = A_TP_O_PERR_CAUSE,
.enable_reg = A_TP_O_PERR_ENABLE,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = tp_other_perr_details,
.actions = NULL,
};
bool fatal;
- fatal = t4_handle_intr(adap, &tp_intr_info, 0, flags);
if (chip_id(adap) > CHELSIO_T6) {
- fatal |= t4_handle_intr(adap, &tp_inic_perr_cause, 0, flags);
+ tp_intr_info.details = t7_tp_intr_details;
+ fatal = t4_handle_intr(adap, &tp_intr_info, 0, flags);
+ fatal |= t4_handle_intr(adap, &tp_cerr_cause, 0, flags);
fatal |= t4_handle_intr(adap, &tp_c_perr_cause, 0, flags);
fatal |= t4_handle_intr(adap, &tp_e_eg_perr_cause, 0, flags);
fatal |= t4_handle_intr(adap, &tp_e_in0_perr_cause, 0, flags);
fatal |= t4_handle_intr(adap, &tp_e_in1_perr_cause, 0, flags);
fatal |= t4_handle_intr(adap, &tp_o_perr_cause, 0, flags);
+ } else {
+ tp_intr_info.details = tp_intr_details;
+ fatal = t4_handle_intr(adap, &tp_intr_info, 0, flags);
}
+ clear_int_cause_reg(adap, &tp_intr_info, flags);
return (fatal);
}
@@ -5133,16 +5362,86 @@ static bool tp_intr_handler(struct adapter *adap, int arg, int flags)
*/
static bool sge_intr_handler(struct adapter *adap, int arg, int flags)
{
+ static const struct intr_details sge_int1_details[] = {
+ { F_PERR_FLM_CREDITFIFO, "SGE FLM credit FIFO parity error" },
+ { F_PERR_IMSG_HINT_FIFO, "SGE IMSG hint FIFO parity error" },
+ { F_PERR_HEADERSPLIT_FIFO3 | F_PERR_HEADERSPLIT_FIFO2,
+ "SGE header split FIFO parity error" },
+ { F_PERR_PAYLOAD_FIFO3 | F_PERR_PAYLOAD_FIFO2,
+ "SGE payload FIFO parity error" },
+ { F_PERR_PC_RSP, "SGE PC response parity error" },
+ { F_PERR_PC_REQ, "SGE PC request parity error" },
+ { 0x003c0000, "SGE DBP PC response FIFO parity error" },
+ { F_PERR_DMARBT, "SGE DMA RBT parity error" },
+ { F_PERR_FLM_DBPFIFO, "SGE FLM DBP FIFO parity error" },
+ { F_PERR_FLM_MCREQ_FIFO, "SGE FLM MC request FIFO parity error" },
+ { F_PERR_FLM_HINTFIFO, "SGE FLM hint FIFO parity error" },
+ { 0x00003c00, "SGE align control FIFO parity error" },
+ { 0x000003c0, "SGE EDMA FIFO parity error" },
+ { 0x0000003c, "SGE PD FIFO parity error" },
+ { F_PERR_ING_CTXT_MIFRSP, "SGE Ingress context MIF response parity error" },
+ { F_PERR_EGR_CTXT_MIFRSP, "SGE Egress context MIF response parity error" },
+ { 0 }
+ };
static const struct intr_info sge_int1_info = {
.name = "SGE_INT_CAUSE1",
.cause_reg = A_SGE_INT_CAUSE1,
.enable_reg = A_SGE_INT_ENABLE1,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = sge_int1_details,
.actions = NULL,
};
- static const struct intr_info sge_int2_info = {
+ static const struct intr_details t7_sge_int2_details[] = {
+ { F_TF_FIFO_PERR, "SGE TF FIFO parity error" },
+ { F_PERR_EGR_DBP_TX_COAL, "SGE egress DBP TX coal parity error" },
+ { F_PERR_DBP_FL_FIFO, "SGE DBP FL FIFO parity error" },
+ { F_DEQ_LL_PERR, "SGE linked list SRAM parity error" },
+ { F_ENQ_PERR, "SGE enq tag SRAM parity error" },
+ { F_DEQ_OUT_PERR, "SGE tbuf deq output FIFO parity error" },
+ { F_BUF_PERR, "SGE tbuf main buffer parity error" },
+ { F_PERR_CONM_SRAM, "SGE CONM SRAM parity error" },
+ { F_PERR_ISW_IDMA3_FIFO | F_PERR_ISW_IDMA2_FIFO |
+ F_PERR_ISW_IDMA1_FIFO | F_PERR_ISW_IDMA0_FIFO,
+ "SGE ISW IDMA FIFO parity error" },
+ { F_PERR_ISW_DBP_FIFO, "SGE ISW DBP FIFO parity error" },
+ { F_PERR_ISW_GTS_FIFO, "SGE ISW GTS FIFO parity error" },
+ { F_PERR_ITP_EVR, "SGE ITP EVR parity error" },
+ { F_PERR_FLM_CNTXMEM, "SGE FLM context memory parity error" },
+ { F_PERR_FLM_L1CACHE, "SGE FLM L1 cache parity error" },
+ { F_SGE_IPP_FIFO_PERR, "SGE IPP FIFO parity error" },
+ { F_PERR_DBP_HP_FIFO, "SGE DBP HP FIFO parity error" },
+ { F_PERR_DB_FIFO, "SGE doorbell FIFO parity error" },
+ { F_PERR_ING_CTXT_CACHE | F_PERR_EGR_CTXT_CACHE,
+ "SGE context cache parity error" },
+ { F_PERR_BASE_SIZE, "SGE base size parity error" },
+ { 0 }
+ };
+ static const struct intr_details t6_sge_int2_details[] = {
+ { F_PERR_DBP_HINT_FL_FIFO, "SGE DBP hint FL FIFO parity error" },
+ { F_PERR_EGR_DBP_TX_COAL, "SGE egress DBP TX coal parity error" },
+ { F_PERR_DBP_FL_FIFO, "SGE DBP FL FIFO parity error" },
+ { F_DEQ_LL_PERR, "SGE tbuf dequeue linked list SRAM parity error" },
+ { F_ENQ_PERR, "SGE tbuf enqueue tag SRAM parity error" },
+ { F_DEQ_OUT_PERR, "SGE tbuf dequeue output FIFO parity error" },
+ { F_BUF_PERR, "SGE tbuf main buffer parity error" },
+ { F_PERR_CONM_SRAM, "SGE CONM SRAM parity error" },
+ { F_PERR_ISW_IDMA1_FIFO, "SGE ISW IDMA FIFO parity error" },
+ { F_PERR_ISW_IDMA0_FIFO, "SGE ISW IDMA FIFO parity error" },
+ { F_PERR_ISW_DBP_FIFO, "SGE ISW DBP FIFO parity error" },
+ { F_PERR_ISW_GTS_FIFO, "SGE ISW GTS FIFO parity error" },
+ { F_PERR_ITP_EVR, "SGE ITP EVR parity error" },
+ { F_PERR_FLM_CNTXMEM, "SGE FLM context memory parity error" },
+ { F_PERR_FLM_L1CACHE, "SGE FLM L1 cache parity error" },
+ { F_PERR_DBP_HINT_FIFO, "SGE DBP hint FIFO parity error" },
+ { F_PERR_DBP_HP_FIFO, "SGE DBP high priority FIFO parity error" },
+ { F_PERR_DB_FIFO, "SGE DBP merge DB FIFO parity error" },
+ { F_PERR_ING_CTXT_CACHE, "SGE ingress context cache parity error" },
+ { F_PERR_EGR_CTXT_CACHE, "SGE egress context cache parity error" },
+ { F_PERR_BASE_SIZE, "SGE base size parity error" },
+ { 0 }
+ };
+ struct intr_info sge_int2_info = {
.name = "SGE_INT_CAUSE2",
.cause_reg = A_SGE_INT_CAUSE2,
.enable_reg = A_SGE_INT_ENABLE2,
@@ -5231,16 +5530,105 @@ static bool sge_intr_handler(struct adapter *adap, int arg, int flags)
.details = NULL,
.actions = NULL,
};
+ static const struct intr_details sge_int4_details[] = {
+ { F_ERR_ISHIFT_UR1 | F_ERR_ISHIFT_UR0, "SGE ishift underrun" },
+ { F_BAR2_EGRESS_LEN_OR_ADDR_ERR, "SGE BAR2 PL access length or alignment error" },
+ { F_ERR_CPL_EXCEED_MAX_IQE_SIZE1 | F_ERR_CPL_EXCEED_MAX_IQE_SIZE0,
+ "SGE CPL exceeds max IQE size" },
+ { F_ERR_WR_LEN_TOO_LARGE3 | F_ERR_WR_LEN_TOO_LARGE2 |
+ F_ERR_WR_LEN_TOO_LARGE1 | F_ERR_WR_LEN_TOO_LARGE0,
+ "SGE WR length too large" },
+ { F_ERR_LARGE_MINFETCH_WITH_TXCOAL3 | F_ERR_LARGE_MINFETCH_WITH_TXCOAL2 |
+ F_ERR_LARGE_MINFETCH_WITH_TXCOAL1 | F_ERR_LARGE_MINFETCH_WITH_TXCOAL0,
+ "SGE invalid MinFetchBurst with TxCoalesce" },
+ { F_COAL_WITH_HP_DISABLE_ERR, "SGE coalesce with HP disable error" },
+ { F_BAR2_EGRESS_COAL0_ERR, "SGE BAR2 PL access addr offset 0" },
+ { F_BAR2_EGRESS_SIZE_ERR, "SGE BAR2 illegal egress QID access" },
+ { F_FLM_PC_RSP_ERR, "SGE FLM PC response error" },
+ { F_ERR_TH3_MAX_FETCH | F_ERR_TH2_MAX_FETCH |
+ F_ERR_TH1_MAX_FETCH | F_ERR_TH0_MAX_FETCH,
+ "SGE max fetch violation" },
+ { F_ERR_RX_CPL_PACKET_SIZE1 | F_ERR_RX_CPL_PACKET_SIZE0,
+ "SGE CPL length mismatch error" },
+ { F_ERR_BAD_UPFL_INC_CREDIT3 | F_ERR_BAD_UPFL_INC_CREDIT2 |
+ F_ERR_BAD_UPFL_INC_CREDIT1 | F_ERR_BAD_UPFL_INC_CREDIT0,
+ "SGE upfl credit wrap error" },
+ { F_ERR_PHYSADDR_LEN0_IDMA1 | F_ERR_PHYSADDR_LEN0_IDMA0,
+ "SGE CPL_RX_PHYS_ADDR length 0 error" },
+ { F_ERR_FLM_INVALID_PKT_DROP1 | F_ERR_FLM_INVALID_PKT_DROP0,
+ "SGE IDMA packet drop due to invalid FLM context" },
+ { F_ERR_UNEXPECTED_TIMER, "SGE unexpected timer error" },
+ { 0 }
+ };
static const struct intr_info sge_int4_info = {
.name = "SGE_INT_CAUSE4",
.cause_reg = A_SGE_INT_CAUSE4,
.enable_reg = A_SGE_INT_ENABLE4,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = sge_int4_details,
.actions = NULL,
};
- static const struct intr_info sge_int5_info = {
+ static const struct intr_details t7_sge_int5_details[] = {
+ { F_ERR_T_RXCRC, "SGE RxCRC error" },
+ { F_PERR_MC_RSPDATA, "SGE MC response data parity error" },
+ { F_PERR_PC_RSPDATA, "SGE PC response data parity error" },
+ { F_PERR_PD_RDRSPDATA, "SGE PD read response data parity error" },
+ { F_PERR_U_RXDATA, "SGE U Rx data parity error" },
+ { F_PERR_UD_RXDATA, "SGE UD Rx data parity error" },
+ { F_PERR_UP_DATA, "SGE uP data parity error" },
+ { F_PERR_CIM2SGE_RXDATA, "SGE CIM2SGE Rx data parity error" },
+ { F_PERR_IMSG_PD_FIFO, "SGE IMSG PD FIFO parity error" },
+ { F_PERR_ULPTX_FIFO1 | F_PERR_ULPTX_FIFO0, "SGE ULPTX FIFO parity error" },
+ { F_PERR_IDMA2IMSG_FIFO3 | F_PERR_IDMA2IMSG_FIFO2 |
+ F_PERR_IDMA2IMSG_FIFO1 | F_PERR_IDMA2IMSG_FIFO0,
+ "SGE IDMA2IMSG FIFO parity error" },
+ { F_PERR_POINTER_DATA_FIFO3 | F_PERR_POINTER_DATA_FIFO2 |
+ F_PERR_POINTER_DATA_FIFO1 | F_PERR_POINTER_DATA_FIFO0,
+ "SGE pointer data FIFO parity error" },
+ { F_PERR_POINTER_HDR_FIFO3 | F_PERR_POINTER_HDR_FIFO2 |
+ F_PERR_POINTER_HDR_FIFO1 | F_PERR_POINTER_HDR_FIFO0,
+ "SGE pointer header FIFO parity error" },
+ { F_PERR_PAYLOAD_FIFO1 | F_PERR_PAYLOAD_FIFO0,
+ "SGE payload FIFO parity error" },
+ { F_PERR_MGT_BAR2_FIFO, "SGE MGT BAR2 FIFO parity error" },
+ { F_PERR_HEADERSPLIT_FIFO1 | F_PERR_HEADERSPLIT_FIFO0,
+ "SGE header split FIFO parity error" },
+ { F_PERR_HINT_DELAY_FIFO, "SGE hint delay FIFO parity error" },
+ { 0 }
+ };
+ static const struct intr_details t6_sge_int5_details[] = {
+ { F_ERR_T_RXCRC, "SGE T RxCRC parity error" },
+ { F_PERR_MC_RSPDATA, "SGE MC response data parity error" },
+ { F_PERR_PC_RSPDATA, "SGE PC response data parity error" },
+ { F_PERR_U_RXDATA | F_PERR_UD_RXDATA, "SGE ULP Rx data parity error" },
+ { F_PERR_UP_DATA, "SGE uP data parity error" },
+ { F_PERR_CIM2SGE_RXDATA, "SGE CIM2SGE Rx data parity error" },
+ { F_PERR_HINT_DELAY_FIFO1 | F_PERR_HINT_DELAY_FIFO0,
+ "SGE hint delay FIFO parity error" },
+ { F_PERR_IMSG_PD_FIFO, "SGE IMSG PD FIFO parity error" },
+ { F_PERR_ULPTX_FIFO1 | F_PERR_ULPTX_FIFO0,
+ "SGE ULPTX FIFO parity error" },
+ { F_PERR_IDMA2IMSG_FIFO1 | F_PERR_IDMA2IMSG_FIFO0,
+ "SGE IDMA2IMSG FIFO parity error" },
+ { F_PERR_POINTER_DATA_FIFO1 | F_PERR_POINTER_DATA_FIFO0,
+ "SGE pointer data FIFO parity error" },
+ { F_PERR_POINTER_HDR_FIFO1 | F_PERR_POINTER_HDR_FIFO0,
+ "SGE pointer header FIFO parity error" },
+ { F_PERR_PAYLOAD_FIFO1 | F_PERR_PAYLOAD_FIFO0,
+ "SGE payload FIFO parity error" },
+ { F_PERR_EDMA_INPUT_FIFO3 | F_PERR_EDMA_INPUT_FIFO2 |
+ F_PERR_EDMA_INPUT_FIFO1 | F_PERR_EDMA_INPUT_FIFO0,
+ "SGE EDMA input FIFO parity error" },
+ { F_PERR_MGT_BAR2_FIFO, "SGE MGT BAR2 FIFO parity error" },
+ { F_PERR_HEADERSPLIT_FIFO1 | F_PERR_HEADERSPLIT_FIFO0,
+ "SGE header split FIFO parity error" },
+ { F_PERR_CIM_FIFO1 | F_PERR_CIM_FIFO0, "SGE CIM FIFO parity error" },
+ { F_PERR_IDMA_SWITCH_OUTPUT_FIFO1 | F_PERR_IDMA_SWITCH_OUTPUT_FIFO0,
+ "SGE IDMA switch output FIFO parity error" },
+ { 0 }
+ };
+ struct intr_info sge_int5_info = {
.name = "SGE_INT_CAUSE5",
.cause_reg = A_SGE_INT_CAUSE5,
.enable_reg = A_SGE_INT_ENABLE5,
@@ -5249,31 +5637,94 @@ static bool sge_intr_handler(struct adapter *adap, int arg, int flags)
.details = NULL,
.actions = NULL,
};
+ static const struct intr_details sge_int6_details[] = {
+ /* T7+ */
+ { 0xe0000000, "SGE fatal DEQ0 DRDY error" },
+ { 0x1c000000, "SGE fatal OUT0 DRDY error" },
+ { F_IMSG_DBG3_STUCK | F_IMSG_DBG2_STUCK |
+ F_IMSG_DBG1_STUCK | F_IMSG_DBG0_STUCK,
+ "SGE IMSG stuck due to insufficient credits" },
+ /* T6 + */
+ { F_ERR_DB_SYNC, "SGE doorbell sync failed" },
+ { F_ERR_GTS_SYNC, "SGE GTS sync failed" },
+ { F_FATAL_LARGE_COAL, "SGE BAR2 payload too large" },
+ { F_PL_BAR2_FRM_ERR, "SGE BAR2 framing error" },
+ { F_SILENT_DROP_TX_COAL, "SGE silent drop of Tx coal WR" },
+ { F_ERR_INV_CTXT4, "SGE context access for invalid queue thread 4" },
+ { F_ERR_BAD_DB_PIDX4, "SGE doorbell pidx too large thread 4" },
+ { F_ERR_BAD_UPFL_INC_CREDIT4, "SGE upfl credit wrap thread 4" },
+ { F_FATAL_TAG_MISMATCH, "SGE doorbell tag mismatch" },
+ { F_FATAL_ENQ_CTL_RDY, "SGE enq_ctl_fifo overflow" },
+ { F_ERR_PC_RSP_LEN3 | F_ERR_PC_RSP_LEN2 |
+ F_ERR_PC_RSP_LEN1 | F_ERR_PC_RSP_LEN0,
+ "SGE PCIe response error for DBP threads" },
+ { F_FATAL_ENQ2LL_VLD, "SGE tbuf fatal_enq2ll_vld" },
+ { F_FATAL_LL_EMPTY, "SGE tbuf fatal_ll_empty" },
+ { F_FATAL_OFF_WDENQ, "SGE tbuf fatal_off_wdenq" },
+ { 0x00000018, "SGE tbuf fatal_deq1_drdy" },
+ { 0x00000006, "SGE tbuf fatal_out1_drdy" },
+ { F_FATAL_DEQ, "SGE tbuf fatal_deq" },
+ { 0 }
+ };
static const struct intr_info sge_int6_info = {
.name = "SGE_INT_CAUSE6",
.cause_reg = A_SGE_INT_CAUSE6,
.enable_reg = A_SGE_INT_ENABLE6,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = sge_int6_details,
.actions = NULL,
};
+ static const struct intr_details sge_int7_details[] = {
+ { F_HINT_FIFO_FULL, "SGE hint FIFO full" },
+ { F_CERR_HINT_DELAY_FIFO, "SGE hint delay FIFO ECC error" },
+ { F_COAL_TIMER_FIFO_PERR, "SGE coalescing timer FIFO parity error" },
+ { F_CMP_FIFO_PERR, "SGE CMP FIFO parity error" },
+ { F_SGE_IPP_FIFO_CERR, "SGE IPP FIFO ECC error" },
+ { F_CERR_ING_CTXT_CACHE | F_CERR_EGR_CTXT_CACHE,
+ "SGE context cache ECC error" },
+ { F_IMSG_CNTX_PERR, "SGE IMSG context parity error" },
+ { F_PD_FIFO_PERR, "SGE PD FIFO parity error" },
+ { F_IMSG_512_FIFO_PERR, "SGE IMSG 512 FIFO parity error" },
+ { F_CPLSW_FIFO_PERR, "SGE CPLSW FIFO parity error" },
+ { F_IMSG_FIFO_PERR, "SGE IMSG FIFO parity error" },
+ { F_CERR_ITP_EVR, "SGE ITP EVR ECC error" },
+ { F_CERR_CONM_SRAM, "SGE CONM SRAM ECC error" },
+ { F_CERR_FLM_CNTXMEM, "SGE FLM context memory ECC error" },
+ { F_CERR_FUNC_QBASE, "SGE function queue base ECC error" },
+ { F_IMSG_CNTX_CERR, "SGE IMSG context ECC error" },
+ { F_PD_FIFO_CERR, "SGE PD FIFO ECC error" },
+ { F_IMSG_512_FIFO_CERR, "SGE IMSG 512 FIFO ECC error" },
+ { F_CPLSW_FIFO_CERR, "SGE CPLSW FIFO ECC error" },
+ { F_IMSG_FIFO_CERR, "SGE IMSG FIFO ECC error" },
+ { 0x0000001e, "SGE header split FIFO ECC error" }, // Bits 4:1
+ { F_CERR_FLM_L1CACHE, "SGE FLM L1 cache ECC error" },
+ { 0 }
+ };
static const struct intr_info sge_int7_info = {
.name = "SGE_INT_CAUSE7",
.cause_reg = A_SGE_INT_CAUSE7,
.enable_reg = A_SGE_INT_ENABLE7,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = sge_int7_details,
.actions = NULL,
};
+ static const struct intr_details sge_int8_details[] = {
+ { F_TRACE_RXPERR, "SGE trace packet parity error" },
+ { F_U3_RXPERR | F_U2_RXPERR | F_U1_RXPERR | F_U0_RXPERR,
+ "SGE ULP interface parity error" },
+ { F_T3_RXPERR | F_T2_RXPERR | F_T1_RXPERR | F_T0_RXPERR,
+ "SGE TP interface parity error" },
+ { 0 }
+ };
static const struct intr_info sge_int8_info = {
.name = "SGE_INT_CAUSE8",
.cause_reg = A_SGE_INT_CAUSE8,
.enable_reg = A_SGE_INT_ENABLE8,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = sge_int8_details,
.actions = NULL,
};
bool fatal;
@@ -5281,8 +5732,14 @@ static bool sge_intr_handler(struct adapter *adap, int arg, int flags)
if (chip_id(adap) <= CHELSIO_T5) {
sge_int3_info.details = sge_int3_details;
+ } else if (chip_id(adap) == CHELSIO_T6) {
+ sge_int3_info.details = t6_sge_int3_details;
+ sge_int2_info.details = t6_sge_int2_details;
+ sge_int5_info.details = t6_sge_int5_details;
} else {
sge_int3_info.details = t6_sge_int3_details;
+ sge_int2_info.details = t7_sge_int2_details;
+ sge_int5_info.details = t7_sge_int5_details;
}
fatal = false;
@@ -5316,6 +5773,19 @@ static bool sge_intr_handler(struct adapter *adap, int arg, int flags)
*/
static bool cim_intr_handler(struct adapter *adap, int arg, int flags)
{
+ static const struct intr_details cim_host_t7_intr_details[] = {
+ { F_CORE7ACCINT, "CIM slave core 7 access interrupt "},
+ { F_CORE6ACCINT, "CIM slave core 6 access interrupt "},
+ { F_CORE5ACCINT, "CIM slave core 5 access interrupt "},
+ { F_CORE4ACCINT, "CIM slave core 4 access interrupt "},
+ { F_CORE3ACCINT, "CIM slave core 3 access interrupt "},
+ { F_CORE2ACCINT, "CIM slave core 2 access interrupt "},
+ { F_CORE1ACCINT, "CIM slave core 1 access interrupt "},
+ { F_TIMER1INT, "CIM TIMER0 interrupt" },
+ { F_TIMER0INT, "CIM TIMER0 interrupt" },
+ { F_PREFDROPINT, "CIM control register prefetch drop" },
+ { 0}
+ };
static const struct intr_details cim_host_intr_details[] = {
/* T6+ */
{ F_PCIE2CIMINTFPARERR, "CIM IBQ PCIe interface parity error" },
@@ -5328,8 +5798,8 @@ static bool cim_intr_handler(struct adapter *adap, int arg, int flags)
{ F_SGE2CIMINTFPARERR, "CIM IBQ SGE interface parity error" },
{ F_ULP2CIMINTFPARERR, "CIM IBQ ULP_TX interface parity error" },
{ F_TP2CIMINTFPARERR, "CIM IBQ TP interface parity error" },
- { F_OBQSGERX1PARERR, "CIM OBQ SGE1_RX parity error" },
- { F_OBQSGERX0PARERR, "CIM OBQ SGE0_RX parity error" },
+ { F_OBQSGERX1PARERR, "CIM OBQ PCIE_RX parity error" },
+ { F_OBQSGERX0PARERR, "CIM OBQ SGE_RX parity error" },
/* T4+ */
{ F_TIEQOUTPARERRINT, "CIM TIEQ outgoing FIFO parity error" },
@@ -5354,16 +5824,17 @@ static bool cim_intr_handler(struct adapter *adap, int arg, int flags)
{ F_PREFDROPINT, "CIM control register prefetch drop" },
{ 0}
};
- static const struct intr_info cim_host_intr_info = {
+ struct intr_info cim_host_intr_info = {
.name = "CIM_HOST_INT_CAUSE",
.cause_reg = A_CIM_HOST_INT_CAUSE,
.enable_reg = A_CIM_HOST_INT_ENABLE,
.fatal = 0x007fffe6,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = cim_host_intr_details,
+ .details = NULL,
.actions = NULL,
};
static const struct intr_details cim_host_upacc_intr_details[] = {
+ { F_CONWRERRINT, "CIM condition write error "},
{ F_EEPROMWRINT, "CIM EEPROM came out of busy state" },
{ F_TIMEOUTMAINT, "CIM PIF MA timeout" },
{ F_TIMEOUTINT, "CIM PIF timeout" },
@@ -5423,18 +5894,54 @@ static bool cim_intr_handler(struct adapter *adap, int arg, int flags)
.details = NULL,
.actions = NULL,
};
+ static const struct intr_details cim_perr_cause_details[] = {
+ { F_T7_MA_CIM_INTFPERR, "MA2CIM interface parity error" },
+ { F_T7_MBHOSTPARERR, "Mailbox Host Read parity error" },
+ { F_MAARBINVRSPTAG, "MA Arbiter Invalid Response Tag (Fatal)" },
+ { F_MAARBFIFOPARERR, "MA Arbiter FIFO Parity Error" },
+ { F_SEMSRAMPARERR, "Semaphore logic SRAM Parity Error" },
+ { F_RSACPARERR, "RSA Code SRAM Parity Error" },
+ { F_RSADPARERR, "RSA Data SRAM Parity Error" },
+ { F_T7_PLCIM_MSTRSPDATAPARERR, "PL2CIM Master response data parity error" },
+ { F_T7_PCIE2CIMINTFPARERR, "IBQ PCIE intf parity error" },
+ { F_T7_NCSI2CIMINTFPARERR, "IBQ NCSI intf parity error" },
+ { F_T7_SGE2CIMINTFPARERR, "IBQ SGE Intf Parity error" },
+ { F_T7_ULP2CIMINTFPARERR, "IBQ ULP_TX intf parity error" },
+ { F_T7_TP2CIMINTFPARERR, "IBQ TP intf parity error" },
+ { F_CORE7PARERR, "Slave Core7 parity error" },
+ { F_CORE6PARERR, "Slave Core6 parity error" },
+ { F_CORE5PARERR, "Slave Core5 parity error" },
+ { F_CORE4PARERR, "Slave Core4 parity error" },
+ { F_CORE3PARERR, "Slave Core3 parity error" },
+ { F_CORE2PARERR, "Slave Core2 parity error" },
+ { F_CORE1PARERR, "Slave Core1 parity error" },
+ { F_GFTPARERR, "GFT block Memory parity error" },
+ { F_MPSRSPDATAPARERR, "MPS lookup interface Response parity error" },
+ { F_ER_RSPDATAPARERR, "Expansion ROM/Flash Interface Response Parity Error" },
+ { F_FLOWFIFOPARERR, "SGE FlowID Prefetch FIFO Parity Error" },
+ { F_OBQSRAMPARERR, "OBQ SRAM Parity Error" },
+ { F_TIEQOUTPARERR, "TIE Queue Outgoing FIFO parity error" },
+ { F_TIEQINPARERR, "TIE Queue Incoming FIFO parity error" },
+ { F_PIFRSPPARERR, "PIF Response interface FIFO Parity error" },
+ { F_PIFREQPARERR, "PIF Request interface FIFO Parity error" },
+ { 0 }
+ };
static const struct intr_info cim_perr_cause = {
.name = "CIM_PERR_CAUSE",
.cause_reg = A_CIM_PERR_CAUSE,
.enable_reg = A_CIM_PERR_ENABLE,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = cim_perr_cause_details,
.actions = NULL,
};
u32 val, fw_err;
bool fatal;
+ if (chip_id(adap) >= CHELSIO_T7)
+ cim_host_intr_info.details = cim_host_t7_intr_details;
+ else
+ cim_host_intr_info.details = cim_host_intr_details;
/*
* When the Firmware detects an internal error which normally wouldn't
* raise a Host Interrupt, it forces a CIM Timer0 interrupt in order
@@ -5477,62 +5984,237 @@ static bool ulprx_intr_handler(struct adapter *adap, int arg, int flags)
{ 0x007fffff, "ULPRX parity error" },
{ 0 }
};
- static const struct intr_info ulprx_intr_info = {
+ static const struct intr_details t6_ulprx_int_cause_details[] = {
+ { F_SE_CNT_MISMATCH_1, "SE count mismatch in channel1" },
+ { F_SE_CNT_MISMATCH_0, "SE count mismatch in channel 0" },
+ { F_CAUSE_CTX_1, "Context access error on channel 1" },
+ { F_CAUSE_CTX_0, "Context access error on channel 0" },
+ { F_CAUSE_FF, "filp-flop based fifos" },
+ { F_CAUSE_APF_1, "Arb prefetch memory, channel 1" },
+ { F_CAUSE_APF_0, "Arb prefetch memory, channel 0" },
+ { F_CAUSE_AF_1, "Arb fetch memory, channel 1" },
+ { F_CAUSE_AF_0, "Arb fetch memory, channel 0" },
+ { F_CAUSE_DDPDF_1, "ddp_data_fifo Fifo, channel 1" },
+ { F_CAUSE_DDPMF_1, "ddp_msg_fifo Fifo, channel 1" },
+ { F_CAUSE_MEMRF_1, "mem_req_fifo_d Fifo, channel 1" },
+ { F_CAUSE_PRSDF_1, "prsr_data_fifo Fifo, channel 1" },
+ { F_CAUSE_DDPDF_0, "ddp_data_fifo Fifo, channel 0" },
+ { F_CAUSE_DDPMF_0, "ddp_msg_fifo Fifo, channel 0" },
+ { F_CAUSE_MEMRF_0, "mem_req_fifo_d Fifo, channel 0" },
+ { F_CAUSE_PRSDF_0, "prsr_data_fifo Fifo, channel 0" },
+ { F_CAUSE_PCMDF_1, "Pcmd Fifo, channel 1" },
+ { F_CAUSE_TPTCF_1, "tpt_ctl_fifo Fifo, channel 1" },
+ { F_CAUSE_DDPCF_1, "ddp_ctl_fifo Fifo, channel 1" },
+ { F_CAUSE_MPARF_1, "mpar_ctl_fifo Fifo, channel 1" },
+ { F_CAUSE_MPARC_1, "mpac_ctl_fifo Fifo, channel 1" },
+ { F_CAUSE_PCMDF_0, "Pcmd Fifo, channel 0" },
+ { F_CAUSE_TPTCF_0, "tpt_ctl_fifo Fifo, channel 0" },
+ { F_CAUSE_DDPCF_0, "ddp_ctl_fifo Fifo, channel 0" },
+ { F_CAUSE_MPARF_0, "mpar_ctl_fifo Fifo, channel 0" },
+ { F_CAUSE_MPARC_0, "mpac_ctl_fifo Fifo, channel 0" },
+ { 0 }
+ };
+ static const struct intr_details t7_ulprx_int_cause_details[] = {
+ { F_CERR_PCMD_FIFO_3, "PCMD FIFO correctable Error3" },
+ { F_CERR_PCMD_FIFO_2, "PCMD FIFO correctable Error2" },
+ { F_CERR_PCMD_FIFO_1, "PCMD FIFO correctable Error1" },
+ { F_CERR_PCMD_FIFO_0, "PCMD FIFO correctable Error0" },
+ { F_CERR_DATA_FIFO_3, "DDP Data FIFO correctable Error3" },
+ { F_CERR_DATA_FIFO_2, "DDP Data FIFO correctable Error2" },
+ { F_CERR_DATA_FIFO_1, "DDP Data FIFO correctable Error1" },
+ { F_CERR_DATA_FIFO_0, "DDP Data FIFO correctable Error0" },
+ { F_SE_CNT_MISMATCH_3, "SE count mismatch in channel3" },
+ { F_SE_CNT_MISMATCH_2, "SE count mismatch in channel2" },
+ { F_T7_SE_CNT_MISMATCH_1, "SE count mismatch in channel1" },
+ { F_T7_SE_CNT_MISMATCH_0, "SE count mismatch in channel 0" },
+ { F_T7_ENABLE_CTX_3, "Context access error on channel 3" },
+ { F_T7_ENABLE_CTX_2, "Context access error on channel 2" },
+ { F_T7_ENABLE_CTX_1, "Context access error on channel 1" },
+ { F_T7_ENABLE_CTX_0, "Context access error on channel 0" },
+ { F_T7_ENABLE_ALN_SDC_ERR_3, "SDC error reported by aligner in channel3" },
+ { F_T7_ENABLE_ALN_SDC_ERR_2, "SDC error reported by aligner in channel2" },
+ { F_T7_ENABLE_ALN_SDC_ERR_1, "SDC error reported by aligner in channel1" },
+ { F_T7_ENABLE_ALN_SDC_ERR_0, "SDC error reported by aligner in channel0" },
+ { 0 }
+ };
+ struct intr_info ulprx_intr_info = {
.name = "ULP_RX_INT_CAUSE",
.cause_reg = A_ULP_RX_INT_CAUSE,
.enable_reg = A_ULP_RX_INT_ENABLE,
.fatal = 0x07ffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = ulprx_intr_details,
+ .details = NULL,
.actions = NULL,
};
+ static const struct intr_details ulprx_int_cause_2_details[] = {
+ { F_ULPRX2MA_INTFPERR, "SDC error reported by ULPRX2MA interface parity checker" },
+ { F_ALN_SDC_ERR_1, "SDC error reported by aligner in channel 1" },
+ { F_ALN_SDC_ERR_0, "SDC error reported by aligner in channel 0" },
+ { F_PF_UNTAGGED_TPT_1, "Parity error from Untagged TPT prefetch fifo channel 1" },
+ { F_PF_UNTAGGED_TPT_0, "Parity error from Untagged TPT prefetch fifo channel 0" },
+ { F_PF_PBL_1, "Parity error from PBL prefetch fifo channel 1" },
+ { F_PF_PBL_0, "Parity error from PBL prefetch fifo channel 0" },
+ { F_DDP_HINT_1, "DDP hint fifo Perr in channel 1" },
+ { F_DDP_HINT_0, "DDP hint fifo Perr in channel 0" },
+ { 0 }
+ };
static const struct intr_info ulprx_intr2_info = {
.name = "ULP_RX_INT_CAUSE_2",
.cause_reg = A_ULP_RX_INT_CAUSE_2,
.enable_reg = A_ULP_RX_INT_ENABLE_2,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = ulprx_int_cause_2_details,
.actions = NULL,
};
+ static const struct intr_details ulprx_int_cause_pcmd_details[] = {
+ { F_CAUSE_PCMD_SFIFO_3, "Small FIFOs, channel 3" },
+ { F_CAUSE_PCMD_FIFO_3, "pcmd_ctl_fifo, channel 3" },
+ { F_CAUSE_PCMD_DDP_HINT_3, "ddp_hint_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_PCMD_TPT_3, "tpt_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_PCMD_DDP_3, "ddp_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_PCMD_MPAR_3, "mpar_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_PCMD_MPAC_3, "mpac_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_PCMD_SFIFO_2, "Small FIFOs, channel 2" },
+ { F_CAUSE_PCMD_FIFO_2, "pcmd_ctl_fifo, channel 2" },
+ { F_CAUSE_PCMD_DDP_HINT_2, "ddp_hint_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_PCMD_TPT_2, "tpt_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_PCMD_DDP_2, "ddp_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_PCMD_MPAR_2, "mpar_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_PCMD_MPAC_2, "mpac_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_PCMD_SFIFO_1, "Small FIFOs, channel 1" },
+ { F_CAUSE_PCMD_FIFO_1, "pcmd_ctl_fifo, channel 1" },
+ { F_CAUSE_PCMD_DDP_HINT_1, "ddp_hint_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_PCMD_TPT_1, "tpt_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_PCMD_DDP_1, "ddp_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_PCMD_MPAR_1, "mpar_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_PCMD_MPAC_1, "mpac_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_PCMD_SFIFO_0, "Small FIFOs, channel 0" },
+ { F_CAUSE_PCMD_FIFO_0, "pcmd_ctl_fifo, channel 0" },
+ { F_CAUSE_PCMD_DDP_HINT_0, "ddp_hint_ctl_fifo FIFO, channel 0" },
+ { F_CAUSE_PCMD_TPT_0, "tpt_ctl_fifo FIFO, channel 0" },
+ { F_CAUSE_PCMD_DDP_0, "ddp_ctl_fifo FIFO, channel 0" },
+ { F_CAUSE_PCMD_MPAR_0, "mpar_ctl_fifo FIFO, channel 0" },
+ { F_CAUSE_PCMD_MPAC_0, "mpac_ctl_fifo FIFO, channel 0" },
+ { 0 }
+ };
static const struct intr_info ulprx_int_cause_pcmd = {
.name = "ULP_RX_INT_CAUSE_PCMD",
.cause_reg = A_ULP_RX_INT_CAUSE_PCMD,
.enable_reg = A_ULP_RX_INT_ENABLE_PCMD,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = ulprx_int_cause_pcmd_details,
.actions = NULL,
};
+ static const struct intr_details ulprx_int_cause_data_details[] = {
+ { F_CAUSE_DATA_SNOOP_3, "Snoop FIFO, channel 3" },
+ { F_CAUSE_DATA_SFIFO_3, "Small FIFO, channel 3" },
+ { F_CAUSE_DATA_FIFO_3, "data_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_DATA_DDP_3, "ddp_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_DATA_CTX_3, "ctx_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_DATA_PARSER_3, "parser_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_DATA_SNOOP_2, "Snoop FIFO, channel 2" },
+ { F_CAUSE_DATA_SFIFO_2, "Small FIFO, channel 2" },
+ { F_CAUSE_DATA_FIFO_2, "data_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_DATA_DDP_2, "ddp_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_DATA_CTX_2, "ctx_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_DATA_PARSER_2, "parser_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_DATA_SNOOP_1, "Snoop FIFO, channel 1" },
+ { F_CAUSE_DATA_SFIFO_1, "Small FIFO, channel 1" },
+ { F_CAUSE_DATA_FIFO_1, "data_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_DATA_DDP_1, "ddp_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_DATA_CTX_1, "ctx_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_DATA_PARSER_1, "parser_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_DATA_SNOOP_0, "Snoop FIFO, channel 0" },
+ { F_CAUSE_DATA_SFIFO_0, "Small FIFO, channel 0" },
+ { F_CAUSE_DATA_FIFO_0, "data_ctl_fifo FIFO, channel 0" },
+ { F_CAUSE_DATA_DDP_0, "ddp_ctl_fifo FIFO, channel 0" },
+ { F_CAUSE_DATA_CTX_0, "ctx_ctl_fifo FIFO, channel 0" },
+ { F_CAUSE_DATA_PARSER_0, "parser_ctl_fifo FIFO, channel 0" },
+ { 0 }
+ };
static const struct intr_info ulprx_int_cause_data = {
.name = "ULP_RX_INT_CAUSE_DATA",
.cause_reg = A_ULP_RX_INT_CAUSE_DATA,
.enable_reg = A_ULP_RX_INT_ENABLE_DATA,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = ulprx_int_cause_data_details,
.actions = NULL,
};
+ static const struct intr_details ulprx_int_cause_arb_details[] = {
+ { F_CAUSE_ARB_PBL_PF_3, "pbl_pf_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_ARB_PF_3, "pf_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_ARB_TPT_PF_3, "tpt_pf_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_ARB_F_3, "f_ctl_fifo FIFO, channel 3" },
+ { F_CAUSE_ARB_PBL_PF_2, "pbl_pf_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_ARB_PF_2, "pf_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_ARB_TPT_PF_2, "tpt_pf_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_ARB_F_2, "f_ctl_fifo FIFO, channel 2" },
+ { F_CAUSE_ARB_PBL_PF_1, "pbl_pf_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_ARB_PF_1, "pf_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_ARB_TPT_PF_1, "tpt_pf_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_ARB_F_1, "f_ctl_fifo FIFO, channel 1" },
+ { F_CAUSE_ARB_PBL_PF_0, "pbl_pf_ctl_fifo FIFO, channel 0" },
+ { F_CAUSE_ARB_PF_0, "pf_ctl_fifo FIFO, channel 0" },
+ { F_CAUSE_ARB_TPT_PF_0, "tpt_pf_ctl_fifo FIFO, channel 0" },
+ { F_CAUSE_ARB_F_0, "f_ctl_fifo FIFO, channel 0" },
+ { 0 }
+ };
static const struct intr_info ulprx_int_cause_arb = {
.name = "ULP_RX_INT_CAUSE_ARB",
.cause_reg = A_ULP_RX_INT_CAUSE_ARB,
.enable_reg = A_ULP_RX_INT_ENABLE_ARB,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = ulprx_int_cause_arb_details,
.actions = NULL,
};
+ static const struct intr_details ulprx_int_cause_interface_details[] = {
+ { F_CAUSE_ULPRX2SBT_RSPPERR, "ULPRX2SBT_RspPerr" },
+ { F_CAUSE_ULPRX2MA_RSPPERR, "ULPRX2MA_RspPerr" },
+ { F_CAUSE_PIO_BUS_PERR, "Pio_Bus_Perr" },
+ { F_CAUSE_PM2ULP_SNOOPDATA_3, "PM2ULP_SnoopData, channel 3" },
+ { F_CAUSE_PM2ULP_SNOOPDATA_2, "PM2ULP_SnoopData, channel 2" },
+ { F_CAUSE_PM2ULP_SNOOPDATA_1, "PM2ULP_SnoopData, channel 1" },
+ { F_CAUSE_PM2ULP_SNOOPDATA_0, "PM2ULP_SnoopData, channel 0" },
+ { F_CAUSE_TLS2ULP_DATA_3, "TLS2ULP_Data, channel 3" },
+ { F_CAUSE_TLS2ULP_DATA_2, "TLS2ULP_Data, channel 2" },
+ { F_CAUSE_TLS2ULP_DATA_1, "TLS2ULP_Data, channel 1" },
+ { F_CAUSE_TLS2ULP_DATA_0, "TLS2ULP_Data, channel 0" },
+ { F_CAUSE_TLS2ULP_PLENDATA_3, "TLS2ULP_PLenData, channel 3" },
+ { F_CAUSE_TLS2ULP_PLENDATA_2, "TLS2ULP_PLenData, channel 2" },
+ { F_CAUSE_TLS2ULP_PLENDATA_1, "TLS2ULP_PLenData, channel 1" },
+ { F_CAUSE_TLS2ULP_PLENDATA_0, "TLS2ULP_PLenData, channel 0" },
+ { F_CAUSE_PM2ULP_DATA_3, "Pm2Ulp_Data, channel 3" },
+ { F_CAUSE_PM2ULP_DATA_2, "Pm2Ulp_Data, channel 2" },
+ { F_CAUSE_PM2ULP_DATA_1, "Pm2Ulp_Data, channel 1" },
+ { F_CAUSE_PM2ULP_DATA_0, "Pm2Ulp_Data, channel 0" },
+ { F_CAUSE_TP2ULP_PCMD_3, "Tp2Ulp_Pcmd, channel 3" },
+ { F_CAUSE_TP2ULP_PCMD_2, "Tp2Ulp_Pcmd, channel 2" },
+ { F_CAUSE_TP2ULP_PCMD_1, "Tp2Ulp_Pcmd, channel 1" },
+ { F_CAUSE_TP2ULP_PCMD_0, "Tp2Ulp_Pcmd, channel 0" },
+ { 0 }
+ };
static const struct intr_info ulprx_int_cause_intf = {
.name = "ULP_RX_INT_CAUSE_INTERFACE",
.cause_reg = A_ULP_RX_INT_CAUSE_INTERFACE,
.enable_reg = A_ULP_RX_INT_ENABLE_INTERFACE,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = ulprx_int_cause_interface_details,
.actions = NULL,
};
bool fatal = false;
+ if (chip_id(adap) <= CHELSIO_T5)
+ ulprx_intr_info.details = ulprx_intr_details;
+ else if (chip_id(adap) <= CHELSIO_T6)
+ ulprx_intr_info.details = t6_ulprx_int_cause_details;
+ else
+ ulprx_intr_info.details = t7_ulprx_int_cause_details;
+
fatal |= t4_handle_intr(adap, &ulprx_intr_info, 0, flags);
if (chip_id(adap) < CHELSIO_T7)
fatal |= t4_handle_intr(adap, &ulprx_intr2_info, 0, flags);
@@ -5559,90 +6241,298 @@ static bool ulptx_intr_handler(struct adapter *adap, int arg, int flags)
{ 0x0fffffff, "ULPTX parity error" },
{ 0 }
};
- static const struct intr_info ulptx_intr_info = {
+ static const struct intr_details t6_ulptx_int_cause_details[] = {
+ { F_PBL_BOUND_ERR_CH3 | F_PBL_BOUND_ERR_CH2 |
+ F_PBL_BOUND_ERR_CH1 | F_PBL_BOUND_ERR_CH0,
+ "PBL address out of bounds" },
+ { F_SGE2ULP_FIFO_PERR_SET3 | F_SGE2ULP_FIFO_PERR_SET2 |
+ F_SGE2ULP_FIFO_PERR_SET1 | F_SGE2ULP_FIFO_PERR_SET0,
+ "SGE2ULP fifo parity error" },
+ { F_CIM2ULP_FIFO_PERR_SET3 | F_CIM2ULP_FIFO_PERR_SET2 |
+ F_CIM2ULP_FIFO_PERR_SET1 | F_CIM2ULP_FIFO_PERR_SET0,
+ "CIM2ULP fifo parity error" },
+ { F_CQE_FIFO_PERR_SET3 | F_CQE_FIFO_PERR_SET2 |
+ F_CQE_FIFO_PERR_SET1 | F_CQE_FIFO_PERR_SET0,
+ "CQE fifo parity error" },
+ { F_PBL_FIFO_PERR_SET3 | F_PBL_FIFO_PERR_SET2 |
+ F_PBL_FIFO_PERR_SET1 | F_PBL_FIFO_PERR_SET0,
+ "PBL fifo parity error" },
+ { F_CMD_FIFO_PERR_SET3 | F_CMD_FIFO_PERR_SET2 |
+ F_CMD_FIFO_PERR_SET1 | F_CMD_FIFO_PERR_SET0,
+ "Command fifo parity error" },
+ { F_LSO_HDR_SRAM_PERR_SET3 | F_LSO_HDR_SRAM_PERR_SET2 |
+ F_LSO_HDR_SRAM_PERR_SET1 | F_LSO_HDR_SRAM_PERR_SET0,
+ "LSO hdr parity error" },
+ { 0 }
+ };
+ struct intr_info ulptx_intr_info = {
.name = "ULP_TX_INT_CAUSE",
.cause_reg = A_ULP_TX_INT_CAUSE,
.enable_reg = A_ULP_TX_INT_ENABLE,
.fatal = 0x0fffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = ulptx_intr_details,
+ .details = NULL,
+ .actions = NULL,
+ };
+ static const struct intr_details ulptx_int_cause_1_details[] = {
+ { F_PBL_BOUND_ERR_CH3 | F_PBL_BOUND_ERR_CH2 |
+ F_PBL_BOUND_ERR_CH1 | F_PBL_BOUND_ERR_CH0,
+ "PBL address out of bounds (configured PBL_ULIMIT/LLIMIT)" },
+ { F_SGE2ULP_FIFO_PERR_SET3 | F_SGE2ULP_FIFO_PERR_SET2 |
+ F_SGE2ULP_FIFO_PERR_SET1 | F_SGE2ULP_FIFO_PERR_SET0,
+ "SGE2ULP FIFO parity error" },
+ { F_CIM2ULP_FIFO_PERR_SET3 | F_CIM2ULP_FIFO_PERR_SET2 |
+ F_CIM2ULP_FIFO_PERR_SET1 | F_CIM2ULP_FIFO_PERR_SET0,
+ "CIM2ULP FIFO parity error" },
+ { F_CQE_FIFO_PERR_SET3 | F_CQE_FIFO_PERR_SET2 |
+ F_CQE_FIFO_PERR_SET1 | F_CQE_FIFO_PERR_SET0,
+ "CQE FIFO parity error" },
+ { F_PBL_FIFO_PERR_SET3 | F_PBL_FIFO_PERR_SET2 |
+ F_PBL_FIFO_PERR_SET1 | F_PBL_FIFO_PERR_SET0,
+ "PBL FIFO parity error" },
+ { F_CMD_FIFO_PERR_SET3 | F_CMD_FIFO_PERR_SET2 |
+ F_CMD_FIFO_PERR_SET1 | F_CMD_FIFO_PERR_SET0,
+ "Command FIFO parity error" },
+ { F_LSO_HDR_SRAM_PERR_SET3 | F_LSO_HDR_SRAM_PERR_SET2 |
+ F_LSO_HDR_SRAM_PERR_SET1 | F_LSO_HDR_SRAM_PERR_SET0,
+ "LSO HDR parity error" },
+ { F_TLS_DSGL_PARERR3 | F_TLS_DSGL_PARERR2 |
+ F_TLS_DSGL_PARERR1 | F_TLS_DSGL_PARERR0,
+ "TLS Glue DSGL FIFO parity error" },
+ { 0 }
+ };
+ static const struct intr_info ulptx_intr_info1 = {
+ .name = "ULP_TX_INT_CAUSE_1",
+ .cause_reg = A_ULP_TX_INT_CAUSE_1,
+ .enable_reg = A_ULP_TX_INT_ENABLE_1,
+ .fatal = 0x0fffffff,
+ .flags = IHF_FATAL_IFF_ENABLED,
+ .details = ulptx_int_cause_1_details,
.actions = NULL,
};
+ static const struct intr_details ulptx_int_cause_2_details[] = {
+ { F_EDMA_IN_FIFO_PERR_SET3 | F_EDMA_IN_FIFO_PERR_SET2 |
+ F_EDMA_IN_FIFO_PERR_SET1 | F_EDMA_IN_FIFO_PERR_SET0,
+ "EDMA input FIFO parity error" },
+ { F_ALIGN_CTL_FIFO_PERR_SET3 | F_ALIGN_CTL_FIFO_PERR_SET2 |
+ F_ALIGN_CTL_FIFO_PERR_SET1 | F_ALIGN_CTL_FIFO_PERR_SET0,
+ "Align control FIFO parity error" },
+ { F_SGE_FIFO_PERR_SET3 | F_SGE_FIFO_PERR_SET2 |
+ F_SGE_FIFO_PERR_SET1 | F_SGE_FIFO_PERR_SET0,
+ "SGE FIFO parity error" },
+ { F_STAG_FIFO_PERR_SET3 | F_STAG_FIFO_PERR_SET2 |
+ F_STAG_FIFO_PERR_SET1 | F_STAG_FIFO_PERR_SET0,
+ "STAG FIFO parity error" },
+ { F_MAP_FIFO_PERR_SET3 | F_MAP_FIFO_PERR_SET2 |
+ F_MAP_FIFO_PERR_SET1 | F_MAP_FIFO_PERR_SET0,
+ "MAP FIFO parity error" },
+ { F_DMA_FIFO_PERR_SET3 | F_DMA_FIFO_PERR_SET2 |
+ F_DMA_FIFO_PERR_SET1 | F_DMA_FIFO_PERR_SET0,
+ "DMA FIFO parity error" },
+ { F_FSO_HDR_SRAM_PERR_SET3 | F_FSO_HDR_SRAM_PERR_SET2 |
+ F_FSO_HDR_SRAM_PERR_SET1 | F_FSO_HDR_SRAM_PERR_SET0,
+ "FSO HDR memory parity error" },
+ { F_T10_PI_SRAM_PERR_SET3 | F_T10_PI_SRAM_PERR_SET2 |
+ F_T10_PI_SRAM_PERR_SET1 | F_T10_PI_SRAM_PERR_SET0,
+ "T10 PI memory parity error" },
+ { 0 }
+ };
static const struct intr_info ulptx_intr_info2 = {
.name = "ULP_TX_INT_CAUSE_2",
.cause_reg = A_ULP_TX_INT_CAUSE_2,
.enable_reg = A_ULP_TX_INT_ENABLE_2,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = ulptx_int_cause_2_details,
.actions = NULL,
};
+ static const struct intr_details ulptx_int_cause_3_details[] = {
+ { F_GF_SGE_FIFO_PARERR3 | F_GF_SGE_FIFO_PARERR2 |
+ F_GF_SGE_FIFO_PARERR1 | F_GF_SGE_FIFO_PARERR0,
+ "GF SGE interface FIFO parity error" },
+ { F_DEDUPE_SGE_FIFO_PARERR3 | F_DEDUPE_SGE_FIFO_PARERR2 |
+ F_DEDUPE_SGE_FIFO_PARERR1 | F_DEDUPE_SGE_FIFO_PARERR0,
+ "DeDupe SGE interface FIFO parity error" },
+ { F_GF3_DSGL_FIFO_PARERR | F_GF2_DSGL_FIFO_PARERR |
+ F_GF1_DSGL_FIFO_PARERR | F_GF0_DSGL_FIFO_PARERR,
+ "GF DSGL FIFO parity error" },
+ { F_DEDUPE3_DSGL_FIFO_PARERR | F_DEDUPE2_DSGL_FIFO_PARERR |
+ F_DEDUPE1_DSGL_FIFO_PARERR | F_DEDUPE0_DSGL_FIFO_PARERR,
+ "DeDupe DSGL FIFO parity error" },
+ { F_XP10_SGE_FIFO_PARERR, "XP10 SGE FIFO parity error (Ch0)" },
+ { F_DSGL_PAR_ERR, "XP10 DSGL interface parity error" },
+ { F_CDDIP_INT, "XP10 decompression interrupt" },
+ { F_CCEIP_INT, "XP10 compression interrupt" },
+ { F_TLS_SGE_FIFO_PARERR3 | F_TLS_SGE_FIFO_PARERR2 |
+ F_TLS_SGE_FIFO_PARERR1 | F_TLS_SGE_FIFO_PARERR0,
+ "TLS Glue SGE FIFO parity error" },
+ { F_ULP2SMARBT_RSP_PERR, "ULP2SMARBT response data/CTL parity error" },
+ { F_ULPTX2MA_RSP_PERR, "ULP2MA response data/CTL parity error" },
+ { F_PCIE2ULP_PERR3 | F_PCIE2ULP_PERR2 |
+ F_PCIE2ULP_PERR1 | F_PCIE2ULP_PERR0,
+ "PCIE2ULP EDMA response parity error" },
+ { F_CIM2ULP_PERR, "CIM2ULP command parity error (all ports)" },
+ { 0 }
+ };
static const struct intr_info ulptx_intr_info3 = {
.name = "ULP_TX_INT_CAUSE_3",
.cause_reg = A_ULP_TX_INT_CAUSE_3,
.enable_reg = A_ULP_TX_INT_ENABLE_3,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = ulptx_int_cause_3_details,
.actions = NULL,
};
+ static const struct intr_details ulptx_int_cause_4_details[] = {
+ { F_XP10_2_ULP_PERR, "XP10 to ULP parity error" },
+ { F_ULP_2_XP10_PERR, "ULP to XP10 parity error" },
+ { F_CMD_FIFO_LB1 | F_CMD_FIFO_LB0,
+ "Command FIFO LB error" },
+ { F_TF_TP_PERR, "TF TP parity error" },
+ { F_TF_SGE_PERR, "TF SGE parity error" },
+ { F_TF_MEM_PERR, "TF memory parity error" },
+ { F_TF_MP_PERR, "TF MP parity error" },
+ { 0 }
+ };
static const struct intr_info ulptx_intr_info4 = {
.name = "ULP_TX_INT_CAUSE_4",
.cause_reg = A_ULP_TX_INT_CAUSE_4,
.enable_reg = A_ULP_TX_INT_ENABLE_4,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = ulptx_int_cause_4_details,
.actions = NULL,
};
+ static const struct intr_details ulptx_int_cause_5_details[] = {
+ { F_DEDUPE_PERR3 | F_DEDUPE_PERR2 |
+ F_DEDUPE_PERR1 | F_DEDUPE_PERR0,
+ "DeDupe parity error" },
+ { F_GF_PERR3 | F_GF_PERR2 |
+ F_GF_PERR1 | F_GF_PERR0,
+ "GF parity error" },
+ { F_SGE2ULP_INV_PERR, "SGE2ULP invalid parity error" },
+ { F_T7_PL_BUSPERR, "PL bus parity error" },
+ { F_TLSTX2ULPTX_PERR3 | F_TLSTX2ULPTX_PERR2 |
+ F_TLSTX2ULPTX_PERR1 | F_TLSTX2ULPTX_PERR0,
+ "TLS to ULP parity error" },
+ { F_XP10_2_ULP_PL_PERR, "XP10 to ULP PL parity error" },
+ { F_ULP_2_XP10_PL_PERR, "ULP to XP10 PL parity error" },
+ { 0 }
+ };
static const struct intr_info ulptx_intr_info5 = {
.name = "ULP_TX_INT_CAUSE_5",
.cause_reg = A_ULP_TX_INT_CAUSE_5,
.enable_reg = A_ULP_TX_INT_ENABLE_5,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = ulptx_int_cause_5_details,
.actions = NULL,
};
+ static const struct intr_details ulptx_int_cause_6_details[] = {
+ { F_DDR_HDR_FIFO_PERR_SET3 | F_DDR_HDR_FIFO_PERR_SET2 |
+ F_DDR_HDR_FIFO_PERR_SET1 | F_DDR_HDR_FIFO_PERR_SET0,
+ "DDR HDR FIFO parity error" },
+ { F_PRE_MP_RSP_PERR_SET3 | F_PRE_MP_RSP_PERR_SET2 |
+ F_PRE_MP_RSP_PERR_SET1 | F_PRE_MP_RSP_PERR_SET0,
+ "Pre-MP response parity error" },
+ { F_PRE_CQE_FIFO_PERR_SET3 | F_PRE_CQE_FIFO_PERR_SET2 |
+ F_PRE_CQE_FIFO_PERR_SET1 | F_PRE_CQE_FIFO_PERR_SET0,
+ "Pre-CQE FIFO parity error" },
+ { F_RSP_FIFO_PERR_SET, "Response FIFO parity error" },
+ { 0 }
+ };
static const struct intr_info ulptx_intr_info6 = {
.name = "ULP_TX_INT_CAUSE_6",
.cause_reg = A_ULP_TX_INT_CAUSE_6,
.enable_reg = A_ULP_TX_INT_ENABLE_6,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = ulptx_int_cause_6_details,
.actions = NULL,
};
+ static const struct intr_details ulptx_int_cause_7_details[] = {
+ { F_TLS_SGE_FIFO_CORERR3 | F_TLS_SGE_FIFO_CORERR2 |
+ F_TLS_SGE_FIFO_CORERR1 | F_TLS_SGE_FIFO_CORERR0,
+ "TLS SGE FIFO correctable error" },
+ { F_LSO_HDR_SRAM_CERR_SET3 | F_LSO_HDR_SRAM_CERR_SET2 |
+ F_LSO_HDR_SRAM_CERR_SET1 | F_LSO_HDR_SRAM_CERR_SET0,
+ "LSO HDR SRAM correctable error" },
+ { F_CORE_CMD_FIFO_CERR_SET_CH3_LB1 | F_CORE_CMD_FIFO_CERR_SET_CH2_LB1 |
+ F_CORE_CMD_FIFO_CERR_SET_CH1_LB1 | F_CORE_CMD_FIFO_CERR_SET_CH0_LB1,
+ "Core command FIFO LB1 correctable error" },
+ { F_CORE_CMD_FIFO_CERR_SET_CH3_LB0 | F_CORE_CMD_FIFO_CERR_SET_CH2_LB0 |
+ F_CORE_CMD_FIFO_CERR_SET_CH1_LB0 | F_CORE_CMD_FIFO_CERR_SET_CH0_LB0,
+ "Core command FIFO LB0 correctable error" },
+ { F_CQE_FIFO_CERR_SET3 | F_CQE_FIFO_CERR_SET2 |
+ F_CQE_FIFO_CERR_SET1 | F_CQE_FIFO_CERR_SET0,
+ "CQE FIFO correctable error" },
+ { F_PRE_CQE_FIFO_CERR_SET3 | F_PRE_CQE_FIFO_CERR_SET2 |
+ F_PRE_CQE_FIFO_CERR_SET1 | F_PRE_CQE_FIFO_CERR_SET0,
+ "Pre-CQE FIFO correctable error" },
+ { 0 }
+ };
static const struct intr_info ulptx_intr_info7 = {
.name = "ULP_TX_INT_CAUSE_7",
.cause_reg = A_ULP_TX_INT_CAUSE_7,
.enable_reg = A_ULP_TX_INT_ENABLE_7,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = ulptx_int_cause_7_details,
.actions = NULL,
};
+ static const struct intr_details ulptx_int_cause_8_details[] = {
+ { F_MEM_RSP_FIFO_CERR_SET3 | F_MEM_RSP_FIFO_CERR_SET2 |
+ F_MEM_RSP_FIFO_CERR_SET1 | F_MEM_RSP_FIFO_CERR_SET0,
+ "Memory response FIFO correctable error" },
+ { F_PI_SRAM_CERR_SET3 | F_PI_SRAM_CERR_SET2 |
+ F_PI_SRAM_CERR_SET1 | F_PI_SRAM_CERR_SET0,
+ "PI SRAM correctable error" },
+ { F_PRE_MP_RSP_CERR_SET3 | F_PRE_MP_RSP_CERR_SET2 |
+ F_PRE_MP_RSP_CERR_SET1 | F_PRE_MP_RSP_CERR_SET0,
+ "Pre-MP response correctable error" },
+ { F_DDR_HDR_FIFO_CERR_SET3 | F_DDR_HDR_FIFO_CERR_SET2 |
+ F_DDR_HDR_FIFO_CERR_SET1 | F_DDR_HDR_FIFO_CERR_SET0,
+ "DDR HDR FIFO correctable error" },
+ { F_CMD_FIFO_CERR_SET3 | F_CMD_FIFO_CERR_SET2 |
+ F_CMD_FIFO_CERR_SET1 | F_CMD_FIFO_CERR_SET0,
+ "Command FIFO correctable error" },
+ { F_GF_SGE_FIFO_CORERR3 | F_GF_SGE_FIFO_CORERR2 |
+ F_GF_SGE_FIFO_CORERR1 | F_GF_SGE_FIFO_CORERR0,
+ "GF SGE FIFO correctable error" },
+ { F_DEDUPE_SGE_FIFO_CORERR3 | F_DEDUPE_SGE_FIFO_CORERR2 |
+ F_DEDUPE_SGE_FIFO_CORERR1 | F_DEDUPE_SGE_FIFO_CORERR0,
+ "DeDupe SGE FIFO correctable error" },
+ { F_RSP_FIFO_CERR_SET, "Response FIFO correctable error" },
+ { 0 }
+ };
static const struct intr_info ulptx_intr_info8 = {
.name = "ULP_TX_INT_CAUSE_8",
.cause_reg = A_ULP_TX_INT_CAUSE_8,
.enable_reg = A_ULP_TX_INT_ENABLE_8,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = ulptx_int_cause_8_details,
.actions = NULL,
};
bool fatal = false;
- fatal |= t4_handle_intr(adap, &ulptx_intr_info, 0, flags);
- if (chip_id(adap) > CHELSIO_T4)
- fatal |= t4_handle_intr(adap, &ulptx_intr_info2, 0, flags);
if (chip_id(adap) > CHELSIO_T6) {
+ fatal |= t4_handle_intr(adap, &ulptx_intr_info1, 0, flags);
+ fatal |= t4_handle_intr(adap, &ulptx_intr_info2, 0, flags);
fatal |= t4_handle_intr(adap, &ulptx_intr_info3, 0, flags);
fatal |= t4_handle_intr(adap, &ulptx_intr_info4, 0, flags);
fatal |= t4_handle_intr(adap, &ulptx_intr_info5, 0, flags);
fatal |= t4_handle_intr(adap, &ulptx_intr_info6, 0, flags);
fatal |= t4_handle_intr(adap, &ulptx_intr_info7, 0, flags);
fatal |= t4_handle_intr(adap, &ulptx_intr_info8, 0, flags);
+ } else {
+ if (chip_id(adap) == CHELSIO_T6)
+ ulptx_intr_info.details = t6_ulptx_int_cause_details;
+ else
+ ulptx_intr_info.details = ulptx_intr_details;
+ fatal |= t4_handle_intr(adap, &ulptx_intr_info, 0, flags);
+ if (chip_id(adap) > CHELSIO_T4)
+ fatal |= t4_handle_intr(adap, &ulptx_intr_info2, 0, flags);
}
return (fatal);
@@ -5671,6 +6561,25 @@ static bool pmtx_dump_dbg_stats(struct adapter *adap, int arg, int flags)
*/
static bool pmtx_intr_handler(struct adapter *adap, int arg, int flags)
{
+ static const struct intr_details t7_pmtx_int_cause_fields[] = {
+ { F_MASTER_PERR, "PM_TX master parity error" },
+ { F_T7_ZERO_C_CMD_ERROR, "PM_TX PCMD with zero length error" },
+ { F_OESPI_COR_ERR, " oespi FIFO Correctable Error" },
+ { F_ICSPI_COR_ERR, " icspi FIFO Correctable Error" },
+ { F_ICSPI_OVFL, " icspi FIFO overflow" },
+ { F_T7_PCMD_LEN_OVFL0, "PMTX channel 0 pcmd too large" },
+ { F_T7_PCMD_LEN_OVFL1, "PMTX channel 1 pcmd too large" },
+ { F_T7_PCMD_LEN_OVFL2, "PMTX channel 2 pcmd too large" },
+ { F_PCMD_LEN_OVFL3, "PMTX channel 2 pcmd too large" },
+ { F_T7_ZERO_C_CMD_ERROR, "PMTX 0-length pcmd" },
+ { 0x00f00000, "PM_TX PCMD length larger than oespi capacity" },
+ { 0x000f0000, "PM_TX icspi 2x FIFO Rx framing error" },
+ { 0x0000f000, "PM_TX icspi FIFO Tx framing error" },
+ { 0x00000f00, "PM_TX oespi FIFO Rx framing error" },
+ { 0x000000f0, "PM_TX oespi FIFO Tx framing error" },
+ { 0x0000000f, "PM_TX oespi 2x FIFO Tx framing error" },
+ { 0 }
+ };
static const struct intr_details pmtx_int_cause_fields[] = {
{ F_PCMD_LEN_OVFL0, "PMTX channel 0 pcmd too large" },
{ F_PCMD_LEN_OVFL1, "PMTX channel 1 pcmd too large" },
@@ -5692,17 +6601,62 @@ static bool pmtx_intr_handler(struct adapter *adap, int arg, int flags)
{ 0xffffffff, -1, pmtx_dump_dbg_stats },
{ 0 },
};
- static const struct intr_info pmtx_int_cause = {
+ struct intr_info pmtx_int_cause = {
.name = "PM_TX_INT_CAUSE",
.cause_reg = A_PM_TX_INT_CAUSE,
.enable_reg = A_PM_TX_INT_ENABLE,
.fatal = 0xffffffff,
- .flags = 0,
- .details = pmtx_int_cause_fields,
+ .flags = IHF_CLR_DELAYED,
+ .details = NULL,
.actions = pmtx_int_cause_actions,
};
+#ifdef notyet
+ static const struct intr_details pmtx_perr_cause_details[] = {
+ { F_ICSPI_OVFL, "icspi FIFO Overflow" },
+ { F_OSPI_OVERFLOW3_TX, " OSPI overflow on channel 3 error." },
+ { F_OSPI_OVERFLOW2_TX, " OSPI overflow on channel 2 error." },
+ { F_OSPI_OVERFLOW1_TX, " OSPI overflow on channel 1 error." },
+ { F_OSPI_OVERFLOW0_TX, " OSPI overflow on channel 0 error." },
+ { F_T7_BUNDLE_LEN_OVFL_EN, "This bit indicates bundle_len_ovfl_err." },
+ { F_T7_M_INTFPERREN, "This bit indicates Parity error from MA interfaces." },
+ { F_T7_1_SDC_ERR,
+ "SDC Error reported by Check PCMD which carries CRC16 from TP-CSide." },
+ { F_MC_WCNT_FIFO_PERR, "MC Interface Write count FIFO Parity error" },
+ { F_MC_WDATA_FIFO_PERR, "MC Interface Write Data FIFO Parity error" },
+ { F_MC_RCNT_FIFO_PERR, "MC Interface Read count FIFO Parity error" },
+ { F_MC_RDATA_FIFO_PERR, "MC Interface Read Data FIFO Parity error" },
+ { F_TOKEN_PAR_ERROR, "c_pcmd, Token FIFO par error" },
+ { F_BUNDLE_LEN_PAR_ERROR, "oespi par error" },
+ { F_OESPI_PAR_ERROR, "oespi par error" },
+ { F_DB_OPTIONS_PAR_ERROR, "db_options par error" },
+ { F_ICSPI_PAR_ERROR, "icspi par error" },
+ { F_C_PCMD_TOKEN_PAR_ERROR, "c_pcmd par error" },
+ { 0 }
+ };
+ static struct intr_info pmtx_perr_cause = {
+ .name = "PM_TX_PERR_CAUSE",
+ .cause_reg = A_PM_TX_PERR_CAUSE,
+ .enable_reg = A_PM_TX_PERR_ENABLE,
+ .fatal = 0xffffffff,
+ .flags = 0,
+ .details = pmtx_perr_cause_details,
+ .actions = NULL,
+ };
+#endif
+ bool fatal;
+
+ if (chip_id(adap) >= CHELSIO_T7)
+ pmtx_int_cause.details = t7_pmtx_int_cause_fields;
+ else
+ pmtx_int_cause.details = pmtx_int_cause_fields;
+ fatal = t4_handle_intr(adap, &pmtx_int_cause, 0, flags);
+#ifdef notyet
+ if (chip_id(adap) >= CHELSIO_T7)
+ fatal |= t4_handle_intr(adap, &pmtx_perr_cause, 0, flags);
+#endif
+ clear_int_cause_reg(adap, &pmtx_int_cause, flags);
- return (t4_handle_intr(adap, &pmtx_int_cause, 0, flags));
+ return (fatal);
}
/*
@@ -5710,6 +6664,20 @@ static bool pmtx_intr_handler(struct adapter *adap, int arg, int flags)
*/
static bool pmrx_intr_handler(struct adapter *adap, int arg, int flags)
{
+ static const struct intr_details t7_pmrx_int_cause_fields[] = {
+ { F_MASTER_PERR, "PM_RX master parity error" },
+ { 0x18000000, "PMRX ospi overflow" },
+ { F_BUNDLE_LEN_OVFL, "PMRX bundle len FIFO overflow" },
+ { F_SDC_ERR, "PMRX SDC error" },
+ { F_ZERO_E_CMD_ERROR, "PMRX 0-length pcmd" },
+ { 0x003c0000, "PMRX iespi FIFO2X Rx framing error" },
+ { 0x0003c000, "PMRX iespi Rx framing error" },
+ { 0x00003c00, "PMRX iespi Tx framing error" },
+ { 0x00000300, "PMRX ocspi Rx framing error" },
+ { 0x000000c0, "PMRX ocspi Tx framing error" },
+ { 0x00000030, "PMRX ocspi FIFO2X Tx framing error" },
+ { 0 }
+ };
static const struct intr_details pmrx_int_cause_fields[] = {
/* T6+ */
{ 0x18000000, "PMRX ospi overflow" },
@@ -5732,17 +6700,94 @@ static bool pmrx_intr_handler(struct adapter *adap, int arg, int flags)
{ F_E_PCMD_PAR_ERROR, "PMRX e_pcmd parity error"},
{ 0 }
};
- static const struct intr_info pmrx_int_cause = {
+ struct intr_info pmrx_int_cause = {
.name = "PM_RX_INT_CAUSE",
.cause_reg = A_PM_RX_INT_CAUSE,
.enable_reg = A_PM_RX_INT_ENABLE,
.fatal = 0x1fffffff,
+ .flags = IHF_FATAL_IFF_ENABLED | IHF_CLR_DELAYED,
+ .details = NULL,
+ .actions = NULL,
+ };
+#ifdef notyet
+ static const struct intr_details pm_rx_int_cause_2_details[] = {
+ { F_CACHE_SRAM_ODD_CERR, "Cache Data Odd SRAM Correctable Error" },
+ { F_CACHE_SRAM_EVEN_CERR, "Cache Data Even SRAM Correctable Error" },
+ { F_CACHE_LRU_LEFT_CERR, "Cache LRU Left SRAM Correctable Error" },
+ { F_CACHE_LRU_RIGHT_CERR, "Cache LRU Right SRAM Correctable Error" },
+ { F_CACHE_ISLAND_CERR, "Cache Island SRAM Correctable Error" },
+ { F_OCSPI_CERR, "ocspi FIFO Correctable Error" },
+ { F_IESPI_CERR, "iespi FIFO Correctable Error" },
+ { F_OCSPI2_RX_FRAMING_ERROR, "ocspi FIFO channel 2 Rx/wr framing error" },
+ { F_OCSPI3_RX_FRAMING_ERROR, "ocspi FIFO channel 3 Rx/wr framing error" },
+ { F_OCSPI2_TX_FRAMING_ERROR, "ocspi FIFO channel 2 Tx/rd framing error" },
+ { F_OCSPI3_TX_FRAMING_ERROR, "ocspi FIFO channel 3 Tx/rd framing error" },
+ { F_OCSPI2_OFIFO2X_TX_FRAMING_ERROR, "ocspi 2x FIFO 2 Tx/rd framing error" },
+ { F_OCSPI3_OFIFO2X_TX_FRAMING_ERROR, "ocspi 2x FIFO 3 Tx/rd framing error" },
+ { 0 }
+ };
+ static struct intr_info pmrx_int_cause2 = {
+ .name = "PM_RX_INT_CAUSE_2",
+ .cause_reg = A_PM_RX_INT_CAUSE_2,
+ .enable_reg = A_PM_RX_INT_ENABLE_2,
+ .fatal = 0x1fffffff,
+ .flags = IHF_FATAL_IFF_ENABLED,
+ .details = pm_rx_int_cause_2_details,
+ .actions = NULL,
+ };
+ static const struct intr_details pm_rx_perr_cause_details[] = {
+ { F_T7_SDC_ERR, "SDC error. CRC provided by TP and PM didn't match." },
+ { F_T7_MA_INTF_SDC_ERR, "MA intf SDC perr" },
+ { F_E_PCMD_PERR, "ulp_rx 2 pm_rx PCMD interface parity error." },
+ { F_CACHE_RSP_DFIFO_PERR, "Cache Response Data FIFO Parity error" },
+ { F_CACHE_SRAM_ODD_PERR, "Cache Odd SRAM error" },
+ { F_CACHE_SRAM_EVEN_PERR, "Cache Even SRAM error" },
+ { F_CACHE_RSVD_PERR, "Cache Reserved Parity error" },
+ { F_CACHE_LRU_LEFT_PERR, "Cache LRU Left SRAM error" },
+ { F_CACHE_LRU_RIGHT_PERR, "Cache LRU Rigth SRAM error" },
+ { F_CACHE_RSP_CMD_PERR, "Cache Response Command FIFO error" },
+ { F_CACHE_SRAM_CMD_PERR, "Cache SRAM Command FIFO error" },
+ { F_CACHE_MA_CMD_PERR, "Cache MA Command FIFO error" },
+ { F_CACHE_TCAM_PERR, "Cache TCAM Parity error" },
+ { F_CACHE_ISLAND_PERR, "Cache island SRAM Parity error" },
+ { F_MC_WCNT_FIFO_PERR, "MC Interface Write count FIFO Parity error" },
+ { F_MC_WDATA_FIFO_PERR, "MC Interface Write Data FIFO Parity error" },
+ { F_MC_RCNT_FIFO_PERR, "MC Interface Read count FIFO Parity error" },
+ { F_MC_RDATA_FIFO_PERR, "MC Interface Read Data FIFO Parity error" },
+ { F_TOKEN_FIFO_PERR, "Token FIFO Parity error" },
+ { F_T7_BUNDLE_LEN_PARERR, "Bundle len fifo had parity error." },
+ { F_OCSPI_PAR_ERROR, "ocspi par error vector" },
+ { F_DB_OPTIONS_PAR_ERROR, "db_options par error" },
+ { F_IESPI_PAR_ERROR, "iespi par error" },
+ { F_E_PCMD_PAR_ERROR, "e_pcmd par error" },
+ { 0 }
+ };
+ static struct intr_info pmrx_perr_cause = {
+ .name = "PM_RX_PERR_CAUSE",
+ .cause_reg = A_PM_RX_PERR_CAUSE,
+ .enable_reg = A_PM_RX_PERR_ENABLE,
+ .fatal = 0x1fffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = pmrx_int_cause_fields,
+ .details = pm_rx_perr_cause_details,
.actions = NULL,
};
+#endif
+ bool fatal;
+
+ if (chip_id(adap) >= CHELSIO_T7) {
+ pmrx_int_cause.details = t7_pmrx_int_cause_fields;
+ fatal = t4_handle_intr(adap, &pmrx_int_cause, 0, flags);
+#ifdef notyet
+ fatal |= t4_handle_intr(adap, &pmrx_int_cause2, 0, flags);
+ fatal |= t4_handle_intr(adap, &pmrx_perr_cause, 0, flags);
+#endif
+ } else {
+ pmrx_int_cause.details = pmrx_int_cause_fields;
+ fatal = t4_handle_intr(adap, &pmrx_int_cause, 0, flags);
+ }
+ clear_int_cause_reg(adap, &pmrx_int_cause, flags);
- return (t4_handle_intr(adap, &pmrx_int_cause, 0, flags));
+ return (fatal);
}
/*
@@ -5751,6 +6796,9 @@ static bool pmrx_intr_handler(struct adapter *adap, int arg, int flags)
static bool cplsw_intr_handler(struct adapter *adap, int arg, int flags)
{
static const struct intr_details cplsw_int_cause_fields[] = {
+ /* T7+ */
+ { F_PERR_CPL_128TO128_3, "CPLSW 128TO128 FIFO3 parity error" },
+ { F_PERR_CPL_128TO128_2, "CPLSW 128TO128 FIFO2 parity error" },
/* T5+ */
{ F_PERR_CPL_128TO128_1, "CPLSW 128TO128 FIFO1 parity error" },
{ F_PERR_CPL_128TO128_0, "CPLSW 128TO128 FIFO0 parity error" },
@@ -5803,6 +6851,8 @@ static bool le_intr_handler(struct adapter *adap, int arg, int flags)
{ 0 }
};
static const struct intr_details t6_le_intr_details[] = {
+ { F_CACHEINTPERR, "Parity error in cache module" },
+ { F_CACHESRAMPERR, "Parity error in data sram " },
{ F_CLIPSUBERR, "LE CLIP CAM reverse substitution error" },
{ F_CLCAMFIFOERR, "LE CLIP CAM internal FIFO error" },
{ F_CTCAMINVLDENT, "Invalid IPv6 CLIP TCAM entry" },
@@ -5865,51 +6915,206 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags)
.details = mps_rx_perr_intr_details,
.actions = NULL,
};
+ static const struct intr_details mps_rx_func_intr_details[] = {
+ { F_MTU_ERR3, "MTU error interrupt enable bit for loopback group 3" },
+ { F_MTU_ERR2, "MTU error interrupt enable bit for loopback group 2" },
+ { F_MTU_ERR1, "MTU error interrupt enable bit for loopback group 1" },
+ { F_MTU_ERR0, "MTU error interrupt enable bit for loopback group 0" },
+ { F_DBG_LEN_ERR, "Oring of len error in traffic transfer b/w internal modules" },
+ { F_DBG_SPI_ERR, "Oring of spi error in traffic transfer b/w internal modules" },
+ { F_DBG_SE_CNT_ERR, "Oring of se cnt error in traffic transfer" },
+ { F_DBG_SPI_LEN_SE_CNT_ERR, "Oring of all se_cnt|len|spi errors" },
+ { 0 }
+ };
+ static const struct intr_info mps_rx_func_intr_info = {
+ .name = "MPS_RX_FUNC_INT_CAUSE",
+ .cause_reg = A_MPS_RX_FUNC_INT_CAUSE,
+ .enable_reg = A_MPS_RX_FUNC_INT_ENABLE,
+ .fatal = 0xffffffff,
+ .flags = IHF_FATAL_IFF_ENABLED,
+ .details = mps_rx_func_intr_details,
+ .actions = NULL,
+ };
+ static const struct intr_details mpsrx_int_cause_2_details[] = {
+ { F_CRYPTO2MPS_RX0_PERR | F_CRYPTO2MPS_RX1_PERR |
+ F_CRYPTO2MPS_RX2_PERR | F_CRYPTO2MPS_RX3_PERR,
+ "Crypto to MPS RX interface parity error" },
+ { F_INIC2MPS_TX1_PERR | F_INIC2MPS_TX0_PERR,
+ "INIC to MPS TX interface parity error" },
+ { F_XGMAC2MPS_RX1_PERR | F_XGMAC2MPS_RX0_PERR,
+ "XGMAC to MPS RX interface parity error" },
+ { F_RX_FINAL_TF_FIFO_PERR,
+ "Final RX token FIFO output parity error" },
+ { F_MPS_DWRR_FIFO_PERR,
+ "MPS DWRR MTU FIFO parity error" },
+ { F_MAC_TF_FIFO_PERR,
+ "MAC token FIFO parity error" },
+ { F_MAC2MPS_PT3_PERR | F_MAC2MPS_PT2_PERR |
+ F_MAC2MPS_PT1_PERR | F_MAC2MPS_PT0_PERR,
+ "MAC to MPS interface parity error" },
+ { F_TP_LPBK_FIFO_PERR, "TP loopback FIFO parity error" },
+ { F_TP_LPBK_TF_PERR, "Loopback token FIFO parity error" },
+ { 0 }
+ };
static const struct intr_info mps_rx_perr_intr_info2 = {
.name = "MPS_RX_PERR_INT_CAUSE2",
.cause_reg = A_MPS_RX_PERR_INT_CAUSE2,
.enable_reg = A_MPS_RX_PERR_INT_ENABLE2,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = mpsrx_int_cause_2_details,
.actions = NULL,
};
+ static const struct intr_details mpsrx_int_cause_3_details[] = {
+ { F_FIFO_REPL_CH3_CERR | F_FIFO_REPL_CH2_CERR |
+ F_FIFO_REPL_CH1_CERR | F_FIFO_REPL_CH0_CERR,
+ "Replication FIFO ECC error" },
+ { F_VLAN_FILTER_RAM_CERR, "VLAN filter SRAM ECC error" },
+ { F_MPS_RX_TD_STAT_FIFO_PERR_CH3 | F_MPS_RX_TD_STAT_FIFO_PERR_CH2 |
+ F_MPS_RX_TD_STAT_FIFO_PERR_CH1 | F_MPS_RX_TD_STAT_FIFO_PERR_CH0,
+ "MPS RX TD status descriptor FIFO parity error" },
+ { F_RPLCT_HDR_FIFO_IN_PERR_CH3 | F_RPLCT_HDR_FIFO_IN_PERR_CH2 |
+ F_RPLCT_HDR_FIFO_IN_PERR_CH1 | F_RPLCT_HDR_FIFO_IN_PERR_CH0,
+ "MPS RX replication header input FIFO parity error" },
+ { F_ID_FIFO_IN_PERR_CH3 | F_ID_FIFO_IN_PERR_CH2 |
+ F_ID_FIFO_IN_PERR_CH1 | F_ID_FIFO_IN_PERR_CH0,
+ "MPS RX replication ID input FIFO parity error" },
+ { F_DESC_HDR2_PERR_CH3 | F_DESC_HDR2_PERR_CH2 |
+ F_DESC_HDR2_PERR_CH1 | F_DESC_HDR2_PERR_CH0,
+ "MPS RX replication descriptor/header2 FIFO parity error" },
+ { F_FIFO_REPL_PERR_CH3 | F_FIFO_REPL_PERR_CH2 |
+ F_FIFO_REPL_PERR_CH1 | F_FIFO_REPL_PERR_CH0,
+ "Replication FIFO parity error" },
+ { F_MPS_RX_TD_PERR_CH3 | F_MPS_RX_TD_PERR_CH2 |
+ F_MPS_RX_TD_PERR_CH1 | F_MPS_RX_TD_PERR_CH0,
+ "MPS RX TD input FIFO parity error" },
+ { 0 }
+ };
static const struct intr_info mps_rx_perr_intr_info3 = {
.name = "MPS_RX_PERR_INT_CAUSE3",
.cause_reg = A_MPS_RX_PERR_INT_CAUSE3,
.enable_reg = A_MPS_RX_PERR_INT_ENABLE3,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = mpsrx_int_cause_3_details,
.actions = NULL,
};
+ static const struct intr_details mpsrx_int_cause_4_details[] = {
+ { F_VNI_MULTICAST_FIFO_ECC_ERR_CH3 | F_VNI_MULTICAST_FIFO_ECC_ERR_CH2,
+ "RX out VNI multicast SRAM ECC error" },
+ { F_HASH_SRAM_CLS_ENG1 | F_HASH_SRAM_CLS_ENG0,
+ "Classification engine hash SRAM ECC error" },
+ { F_CLS_TCAM_SRAM_CLS_ENG1 | F_CLS_TCAM_SRAM_CLS_ENG0,
+ "Classification engine TCAM SRAM ECC error" },
+ { F_CLS_TCAM_CRC_SRAM_CLS_ENG1 | F_CLS_TCAM_CRC_SRAM_CLS_ENG0,
+ "Classification engine TCAM CRC SRAM ECC error" },
+ { F_DWRR_CH_FIFO_ECC_ERR, "DWRR output FIFO ECC error" },
+ { F_MAC_RX_FIFO_ECC_ERR, "MAC RX FIFO ECC error" },
+ { F_LPBK_RX_FIFO_ECC_ERR, "Loopback RX FIFO ECC error" },
+ { F_CRS_DATA_STORE_N_FWD_CH3 | F_CRS_DATA_STORE_N_FWD_CH2 |
+ F_CRS_DATA_STORE_N_FWD_CH1 | F_CRS_DATA_STORE_N_FWD_CH0,
+ "CRS store and forward FIFO ECC error" },
+ { F_TRACE_FWD_FIFO_CERR_CH3 | F_TRACE_FWD_FIFO_CERR_CH2 |
+ F_TRACE_FWD_FIFO_CERR_CH1 | F_TRACE_FWD_FIFO_CERR_CH0,
+ "Trace packet forward FIFO ECC error" },
+ { F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH3 | F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH2 |
+ F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH1 | F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH0,
+ "Transparent encap forward FIFO ECC error" },
+ { F_PTP_TRACE_FWD_FIFO_CERR_CH3 | F_PTP_TRACE_FWD_FIFO_CERR_CH2 |
+ F_PTP_TRACE_FWD_FIFO_CERR_CH1 | F_PTP_TRACE_FWD_FIFO_CERR_CH0,
+ "PTP packet forward FIFO ECC error" },
+ { 0 }
+ };
static const struct intr_info mps_rx_perr_intr_info4 = {
.name = "MPS_RX_PERR_INT_CAUSE4",
.cause_reg = A_MPS_RX_PERR_INT_CAUSE4,
.enable_reg = A_MPS_RX_PERR_INT_ENABLE4,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = mpsrx_int_cause_4_details,
.actions = NULL,
};
+ static const struct intr_details mpsrx_int_cause_5_details[] = {
+ { F_MPS2CRYP_RX_FIFO3_PERR | F_MPS2CRYP_RX_FIFO2_PERR |
+ F_MPS2CRYP_RX_FIFO1_PERR | F_MPS2CRYP_RX_FIFO0_PERR,
+ "MPS to Crypto RX interface FIFO parity error" },
+ { F_VNI_MULTICAST_SRAM2_PERR | F_VNI_MULTICAST_SRAM1_PERR |
+ F_VNI_MULTICAST_SRAM0_PERR,
+ "VNI multicast SRAM parity error" },
+ { F_MAC_MULTICAST_SRAM4_PERR | F_MAC_MULTICAST_SRAM3_PERR |
+ F_MAC_MULTICAST_SRAM2_PERR | F_MAC_MULTICAST_SRAM1_PERR |
+ F_MAC_MULTICAST_SRAM0_PERR,
+ "MAC multicast SRAM parity error" },
+ { F_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR | F_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR |
+ F_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR | F_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR,
+ "IPsec header update storing FIFO parity error" },
+ { F_MEM_WRAP_CR2MPS_RX_FIFO3_PERR | F_MEM_WRAP_CR2MPS_RX_FIFO2_PERR |
+ F_MEM_WRAP_CR2MPS_RX_FIFO1_PERR | F_MEM_WRAP_CR2MPS_RX_FIFO0_PERR,
+ "IPsec storing FIFO parity error" },
+ { F_MEM_WRAP_NON_IPSEC_FIFO3_PERR | F_MEM_WRAP_NON_IPSEC_FIFO2_PERR |
+ F_MEM_WRAP_NON_IPSEC_FIFO1_PERR | F_MEM_WRAP_NON_IPSEC_FIFO0_PERR,
+ "Non-IPsec storing FIFO parity error" },
+ { F_MEM_WRAP_TP_DB_REQ_FIFO3_PERR | F_MEM_WRAP_TP_DB_REQ_FIFO2_PERR |
+ F_MEM_WRAP_TP_DB_REQ_FIFO1_PERR | F_MEM_WRAP_TP_DB_REQ_FIFO0_PERR,
+ "TP DB request storing FIFO parity error" },
+ { F_MEM_WRAP_CNTRL_FIFO3_PERR | F_MEM_WRAP_CNTRL_FIFO2_PERR |
+ F_MEM_WRAP_CNTRL_FIFO1_PERR | F_MEM_WRAP_CNTRL_FIFO0_PERR,
+ "Header flit storing FIFO parity error" },
+ { 0 }
+ };
static const struct intr_info mps_rx_perr_intr_info5 = {
.name = "MPS_RX_PERR_INT_CAUSE5",
.cause_reg = A_MPS_RX_PERR_INT_CAUSE5,
.enable_reg = A_MPS_RX_PERR_INT_ENABLE5,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = mpsrx_int_cause_5_details,
.actions = NULL,
};
+ static const struct intr_details mpsrx_int_cause_6_details[] = {
+ { F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR | F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR |
+ F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR | F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR,
+ "IPsec header update storing FIFO parity error" },
+ { F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO3_PERR | F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO2_PERR |
+ F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO1_PERR | F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO0_PERR,
+ "IPsec updated header only storing FIFO parity error" },
+ { F_MEM_WRAP_CR2MPS_RX_FIFO3_PERR | F_MEM_WRAP_CR2MPS_RX_FIFO2_PERR |
+ F_MEM_WRAP_CR2MPS_RX_FIFO1_PERR | F_MEM_WRAP_CR2MPS_RX_FIFO0_PERR,
+ "IPsec storing FIFO parity error" },
+ { F_MEM_WRAP_NON_IPSEC_FIFO3_PERR | F_MEM_WRAP_NON_IPSEC_FIFO2_PERR |
+ F_MEM_WRAP_NON_IPSEC_FIFO1_PERR | F_MEM_WRAP_NON_IPSEC_FIFO0_PERR,
+ "Non-IPsec storing FIFO parity error" },
+ { F_MEM_WRAP_TP_DB_REQ_FIFO3_PERR | F_MEM_WRAP_TP_DB_REQ_FIFO2_PERR |
+ F_MEM_WRAP_TP_DB_REQ_FIFO1_PERR | F_MEM_WRAP_TP_DB_REQ_FIFO0_PERR,
+ "TP DB request storing FIFO parity error" },
+ { F_MEM_WRAP_CNTRL_FIFO3_PERR | F_MEM_WRAP_CNTRL_FIFO2_PERR |
+ F_MEM_WRAP_CNTRL_FIFO1_PERR | F_MEM_WRAP_CNTRL_FIFO0_PERR,
+ "Header flit storing FIFO parity error" },
+ { 0 }
+ };
static const struct intr_info mps_rx_perr_intr_info6 = {
.name = "MPS_RX_PERR_INT_CAUSE6",
.cause_reg = A_MPS_RX_PERR_INT_CAUSE6,
.enable_reg = A_MPS_RX_PERR_INT_ENABLE6,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = mpsrx_int_cause_6_details,
.actions = NULL,
};
+ static const struct intr_details t7_mpstx_int_cause_details[] = {
+ { F_T7_PORTERR, "Tx received a frame for TP destined to a disable port" },
+ { F_T7_FRMERR, "Framing error in received Data from TP or Data to MAC" },
+ { F_T7_SECNTERR, "SOP-EOP count error in received Data from TP or Data to MAC" },
+ { F_T7_BUBBLE, "Valid is deasserted between SOP and EOP" },
+ { F_TX_TF_FIFO_PERR, "Parity error of TX token fifo" },
+ { F_TX_FIFO_PERR, "Parity error of TX MPS2MAC underrun fifo" },
+ { 0x0003c000, "Parity error of fifo storing non-ipsec +1 flit ipsec pkt" },
+ { 0x00003fc0, "Interface parity error on TP/Crypto to MPS TX" },
+ { F_NCSI2MPS, "interface Parity Error on ncsi2mps_tx_ch3" },
+ { F_NCSIFIFO, "Parity Error in mps_tx_arbiter input FIFO (from NCSI)" },
+ { 0x0000000f, "Parity Error in mps_tx_arbiter input FIFO (from TP)" },
+ { 0 }
+ };
static const struct intr_details mps_tx_intr_details[] = {
{ F_PORTERR, "MPS Tx destination port is disabled" },
{ F_FRMERR, "MPS Tx framing error" },
@@ -5921,22 +7126,27 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags)
{ V_TPFIFO(M_TPFIFO), "MPS Tx TP FIFO parity error" },
{ 0 }
};
- static const struct intr_info mps_tx_intr_info = {
+ struct intr_info mps_tx_intr_info = {
.name = "MPS_TX_INT_CAUSE",
.cause_reg = A_MPS_TX_INT_CAUSE,
.enable_reg = A_MPS_TX_INT_ENABLE,
.fatal = 0x1ffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = mps_tx_intr_details,
+ .details = NULL,
.actions = NULL,
};
+ static const struct intr_details mpstx_int_cause_2_details[] = {
+ { F_TX_FIFO_PERR, "ECC error of TX MPS2MAC underrun fifo" },
+ { 0x0000000f, "ECC error of fifo storing non-ipsec +1 flit ipsec pkt" },
+ { 0 }
+ };
static const struct intr_info mps_tx_intr_info2 = {
.name = "MPS_TX_INT2_CAUSE",
.cause_reg = A_MPS_TX_INT2_CAUSE,
.enable_reg = A_MPS_TX_INT2_ENABLE,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = mpstx_int_cause_2_details,
.actions = NULL,
};
static const struct intr_info mps_tx_intr_info3 = {
@@ -5972,22 +7182,51 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags)
.details = mps_trc_intr_details,
.actions = NULL,
};
+ static const struct intr_details t7_mps_trc_intr_details[] = {
+ { F_T7_TRCPLERRENB, "TRC PL error" },
+ { F_T7_MISCPERR, "TRC header register parity error" },
+ { 0x0000ff00, "TRC packet FIFO parity error" },
+ { 0x000000ff, "TRC filter memory parity error" },
+ { 0 }
+ };
static const struct intr_info t7_mps_trc_intr_info = {
.name = "MPS_TRC_INT_CAUSE",
.cause_reg = A_T7_MPS_TRC_INT_CAUSE,
.enable_reg = A_T7_MPS_TRC_INT_ENABLE,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = mps_trc_intr_details,
+ .details = t7_mps_trc_intr_details,
.actions = NULL,
};
+ static const struct intr_details t7_trc_int_cause2_details[] = {
+ { 0x0001e000, "TRC Tx2Rx down-converter correctable error" },
+ { 0x00001800, "TRC MPS2MAC down-converter correctable error" },
+ { 0x00000600, "TRC MAC2MPS down-converter correctable error" },
+ { 0x000001e0, "TRC Tx2Rx down-converter parity error" },
+ { 0x00000018, "TRC MAC2MPS down-converter parity error" },
+ { 0x00000006, "TRC MPS2MAC down-converter parity error" },
+ { 0 }
+ };
static const struct intr_info t7_mps_trc_intr_info2 = {
.name = "MPS_TRC_INT_CAUSE2",
.cause_reg = A_MPS_TRC_INT_CAUSE2,
.enable_reg = A_MPS_TRC_INT_ENABLE2,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = t7_trc_int_cause2_details,
+ .actions = NULL,
+ };
+ static const struct intr_details mps_stat_intr_details[] = {
+ { F_PLREADSYNCERR, "MPS pl read sync error" },
+ { 0 }
+ };
+ static const struct intr_info mps_stat_intr_info = {
+ .name = "MPS_STAT_INT_CAUSE",
+ .cause_reg = A_MPS_STAT_INT_CAUSE,
+ .enable_reg = A_MPS_STAT_INT_ENABLE,
+ .fatal = 0xf,
+ .flags = IHF_FATAL_IFF_ENABLED,
+ .details = mps_stat_intr_details,
.actions = NULL,
};
static const struct intr_details mps_stat_sram_intr_details[] = {
@@ -6030,6 +7269,9 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags)
.actions = NULL,
};
static const struct intr_details mps_cls_intr_details[] = {
+ { F_T7_PLERRENB, "PL error"},
+ { F_CIM2MPS_INTF_PAR, "cim2mps interface parity"},
+ { F_TCAM_CRC_SRAM, "tcam crc sram parity error"},
{ F_HASHSRAM, "MPS hash SRAM parity error" },
{ F_MATCHTCAM, "MPS match TCAM parity error" },
{ F_MATCHSRAM, "MPS match SRAM parity error" },
@@ -6058,9 +7300,14 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags)
.actions = NULL,
};
bool fatal = false;
+ if (chip_id(adap) >= CHELSIO_T7)
+ mps_tx_intr_info.details = t7_mpstx_int_cause_details;
+ else
+ mps_tx_intr_info.details = mps_tx_intr_details;
fatal |= t4_handle_intr(adap, &mps_rx_perr_intr_info, 0, flags);
if (chip_id(adap) > CHELSIO_T6) {
+ fatal |= t4_handle_intr(adap, &mps_rx_func_intr_info, 0, flags);
fatal |= t4_handle_intr(adap, &mps_rx_perr_intr_info2, 0, flags);
fatal |= t4_handle_intr(adap, &mps_rx_perr_intr_info3, 0, flags);
fatal |= t4_handle_intr(adap, &mps_rx_perr_intr_info4, 0, flags);
@@ -6076,6 +7323,7 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags)
fatal |= t4_handle_intr(adap, &t7_mps_trc_intr_info2, 0, flags);
} else
fatal |= t4_handle_intr(adap, &mps_trc_intr_info, 0, flags);
+ fatal |= t4_handle_intr(adap, &mps_stat_intr_info, 0, flags);
fatal |= t4_handle_intr(adap, &mps_stat_sram_intr_info, 0, flags);
fatal |= t4_handle_intr(adap, &mps_stat_tx_intr_info, 0, flags);
fatal |= t4_handle_intr(adap, &mps_stat_rx_intr_info, 0, flags);
@@ -6087,7 +7335,6 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags)
t4_read_reg(adap, A_MPS_INT_CAUSE); /* flush */
return (fatal);
-
}
/*
@@ -6096,7 +7343,7 @@ static bool mps_intr_handler(struct adapter *adap, int arg, int flags)
static bool mem_intr_handler(struct adapter *adap, int idx, int flags)
{
static const char name[4][5] = { "EDC0", "EDC1", "MC0", "MC1" };
- unsigned int count_reg, v;
+ unsigned int count_reg = 0, v;
static const struct intr_details mem_intr_details[] = {
{ F_ECC_UE_INT_CAUSE, "Uncorrectable ECC data error(s)" },
{ F_ECC_CE_INT_CAUSE, "Correctable ECC data error(s)" },
@@ -6104,10 +7351,10 @@ static bool mem_intr_handler(struct adapter *adap, int idx, int flags)
{ 0 }
};
static const struct intr_details t7_mem_intr_details[] = {
- { F_DDRPHY_INT_CAUSE, "DDRPHY" },
- { F_DDRCTL_INT_CAUSE, "DDRCTL" },
- { F_T7_ECC_CE_INT_CAUSE, "Correctable ECC data error(s)" },
+ { F_DDRPHY_INT_CAUSE, "DDR PHY" },
+ { F_DDRCTL_INT_CAUSE, "DDR Controller" },
{ F_T7_ECC_UE_INT_CAUSE, "Uncorrectable ECC data error(s)" },
+ { F_T7_ECC_CE_INT_CAUSE, "Correctable ECC data error(s)" },
{ F_PERR_INT_CAUSE, "FIFO parity error" },
{ 0 }
};
@@ -6115,8 +7362,8 @@ static bool mem_intr_handler(struct adapter *adap, int idx, int flags)
struct intr_info ii = {
.name = &rname[0],
.fatal = F_PERR_INT_CAUSE | F_ECC_UE_INT_CAUSE,
+ .flags = IHF_CLR_DELAYED,
.details = mem_intr_details,
- .flags = 0,
.actions = NULL,
};
bool fatal = false;
@@ -6137,15 +7384,6 @@ static bool mem_intr_handler(struct adapter *adap, int idx, int flags)
count_reg = EDC_T5_REG(A_EDC_H_ECC_STATUS, i);
}
fatal |= t4_handle_intr(adap, &ii, 0, flags);
- if (chip_id(adap) > CHELSIO_T6) {
- snprintf(rname, sizeof(rname), "EDC%u_PAR_CAUSE", i);
- ii.cause_reg = EDC_T5_REG(A_EDC_H_PAR_CAUSE, i);
- ii.enable_reg = EDC_T5_REG(A_EDC_H_PAR_ENABLE, i);
- ii.fatal = 0xffffffff;
- ii.details = NULL;
- ii.flags = IHF_FATAL_IFF_ENABLED;
- fatal |= t4_handle_intr(adap, &ii, 0, flags);
- }
break;
case MEM_MC1:
if (is_t4(adap) || is_t6(adap))
@@ -6167,52 +7405,30 @@ static bool mem_intr_handler(struct adapter *adap, int idx, int flags)
ii.enable_reg = MC_T7_REG(A_T7_MC_P_INT_ENABLE, i);
ii.fatal = F_PERR_INT_CAUSE | F_T7_ECC_UE_INT_CAUSE;
ii.details = t7_mem_intr_details;
- count_reg = MC_T7_REG(A_T7_MC_P_ECC_STATUS, i);
- }
- fatal |= t4_handle_intr(adap, &ii, 0, flags);
-
- snprintf(rname, sizeof(rname), "MC%u_PAR_CAUSE", i);
- if (is_t4(adap)) {
- ii.cause_reg = A_MC_PAR_CAUSE;
- ii.enable_reg = A_MC_PAR_ENABLE;
- } else if (chip_id(adap) < CHELSIO_T7) {
- ii.cause_reg = MC_REG(A_MC_P_PAR_CAUSE, i);
- ii.enable_reg = MC_REG(A_MC_P_PAR_ENABLE, i);
- } else {
- ii.cause_reg = MC_T7_REG(A_T7_MC_P_PAR_CAUSE, i);
- ii.enable_reg = MC_T7_REG(A_T7_MC_P_PAR_ENABLE, i);
}
- ii.fatal = 0xffffffff;
- ii.details = NULL;
- ii.flags = IHF_FATAL_IFF_ENABLED;
fatal |= t4_handle_intr(adap, &ii, 0, flags);
-
- if (chip_id(adap) > CHELSIO_T6) {
- snprintf(rname, sizeof(rname), "MC%u_DDRCTL_INT_CAUSE", i);
- ii.cause_reg = MC_T7_REG(A_MC_P_DDRCTL_INT_CAUSE, i);
- ii.enable_reg = MC_T7_REG(A_MC_P_DDRCTL_INT_ENABLE, i);
- fatal |= t4_handle_intr(adap, &ii, 0, flags);
- }
break;
}
- v = t4_read_reg(adap, count_reg);
- if (v != 0) {
- if (G_ECC_UECNT(v) != 0 && !(flags & IHF_NO_SHOW)) {
- CH_ALERT(adap,
- " %s: %u uncorrectable ECC data error(s)\n",
- name[idx], G_ECC_UECNT(v));
- }
- if (G_ECC_CECNT(v) != 0 && !(flags & IHF_NO_SHOW)) {
- if (idx <= MEM_EDC1)
- t4_edc_err_read(adap, idx);
- CH_WARN_RATELIMIT(adap,
- " %s: %u correctable ECC data error(s)\n",
- name[idx], G_ECC_CECNT(v));
+ if (count_reg != 0) {
+ v = t4_read_reg(adap, count_reg);
+ if (v != 0) {
+ if (G_ECC_UECNT(v) != 0 && !(flags & IHF_NO_SHOW)) {
+ CH_ALERT(adap,
+ " %s: %u uncorrectable ECC data error(s)\n",
+ name[idx], G_ECC_UECNT(v));
+ }
+ if (G_ECC_CECNT(v) != 0 && !(flags & IHF_NO_SHOW)) {
+ if (idx <= MEM_EDC1)
+ t4_edc_err_read(adap, idx);
+ CH_WARN_RATELIMIT(adap,
+ " %s: %u correctable ECC data error(s)\n",
+ name[idx], G_ECC_CECNT(v));
+ }
+ t4_write_reg(adap, count_reg, 0xffffffff);
}
- t4_write_reg(adap, count_reg, 0xffffffff);
}
-
+ clear_int_cause_reg(adap, &ii, flags);
return (fatal);
}
@@ -6231,14 +7447,13 @@ static bool ma_wrap_status(struct adapter *adap, int arg, int flags)
return (false);
}
-
/*
* MA interrupt handler.
*/
static bool ma_intr_handler(struct adapter *adap, int arg, int flags)
{
static const struct intr_action ma_intr_actions[] = {
- { F_MEM_WRAP_INT_CAUSE, 0, ma_wrap_status },
+ { F_MEM_WRAP_INT_CAUSE, -1, ma_wrap_status },
{ 0 },
};
static const struct intr_info ma_intr_info = {
@@ -6284,10 +7499,29 @@ static bool ma_intr_handler(struct adapter *adap, int arg, int flags)
*/
static bool smb_intr_handler(struct adapter *adap, int arg, int flags)
{
- static const struct intr_details smb_int_cause_fields[] = {
- { F_MSTTXFIFOPARINT, "SMB master Tx FIFO parity error" },
- { F_MSTRXFIFOPARINT, "SMB master Rx FIFO parity error" },
- { F_SLVFIFOPARINT, "SMB slave FIFO parity error" },
+ static const struct intr_details smb_int_cause_details[] = {
+ { F_MSTTXFIFOPARINT, "Master has Parity Error in Tx Fifo" },
+ { F_MSTRXFIFOPARINT, "Master has Parity Error in Rx Fifo" },
+ { F_SLVFIFOPARINT, "Slave has Parity Error in Fifo" },
+ { F_SLVUNEXPBUSSTOPINT, "Slave get Unexpected BusStop" },
+ { F_SLVUNEXPBUSSTARTINT, "Slave get Unexpected BusStart" },
+ { F_SLVCOMMANDCODEINVINT, "Slave get Invalid Command Code" },
+ { F_SLVBYTECNTERRINT, "Slave get Erroneous ByteCount value" },
+ { F_SLVUNEXPACKMSTINT, "Slave get Unexpected Ack from Master" },
+ { F_SLVUNEXPNACKMSTINT, "Slave get Unexpected Nack from Master" },
+ { F_SLVNOBUSSTOPINT, "Slave did not get Bus Stop" },
+ { F_SLVNOREPSTARTINT, "Slave has no Repeated Start" },
+ { F_SLVRXADDRINT, "Slave has Address Error" },
+ { F_SLVRXPECERRINT, "Slave has Pec Error" },
+ { F_SLVPREPTOARPINT, "PL has invalid request" },
+ { F_SLVTIMEOUTINT, "Slave has timed out" },
+ { F_SLVERRINT, "Slave detected error during the current transfer" },
+ { F_SLVDONEINT, "Slave has completed the current transaction" },
+ { F_SLVRXRDYINT, "Slave has received bytes to be processed by uP" },
+ { F_MSTTIMEOUTINT, "Master has timed out" },
+ { F_MSTNACKINT, "Master has detected a NAck on the transfer" },
+ { F_MSTLOSTARBINT, "Master has lost arbitration all the timeline" },
+ { F_MSTDONEINT, "Master has completed the current transaction" },
{ 0 }
};
static const struct intr_info smb_int_cause = {
@@ -6296,9 +7530,10 @@ static bool smb_intr_handler(struct adapter *adap, int arg, int flags)
.enable_reg = A_SMB_INT_ENABLE,
.fatal = F_SLVFIFOPARINT | F_MSTRXFIFOPARINT | F_MSTTXFIFOPARINT,
.flags = 0,
- .details = smb_int_cause_fields,
+ .details = smb_int_cause_details,
.actions = NULL,
};
+
return (t4_handle_intr(adap, &smb_int_cause, 0, flags));
}
@@ -6308,6 +7543,7 @@ static bool smb_intr_handler(struct adapter *adap, int arg, int flags)
static bool ncsi_intr_handler(struct adapter *adap, int arg, int flags)
{
static const struct intr_details ncsi_int_cause_fields[] = {
+ { F_CIM2NC_PERR, " CIM to NC parity error" },
{ F_CIM_DM_PRTY_ERR, "NC-SI CIM parity error" },
{ F_MPS_DM_PRTY_ERR, "NC-SI MPS parity error" },
{ F_TXFIFO_PRTY_ERR, "NC-SI Tx FIFO parity error" },
@@ -6324,13 +7560,31 @@ static bool ncsi_intr_handler(struct adapter *adap, int arg, int flags)
.details = ncsi_int_cause_fields,
.actions = NULL,
};
+ static const struct intr_details ncsi_xgmac0_int_cause_details[] = {
+ { F_XAUIPCSDECERR, "RGMII PCS DEC Error" },
+ { F_RGMIIRXFIFOOVERFLOW, "RGMII receive FIFO over flow" },
+ { F_RGMIIRXFIFOUNDERFLOW, "RGMII receive FIFO under flow" },
+ { F_RXPKTSIZEERROR, "Receive over size packet" },
+ { F_WOLPATDETECTED, "WOL pattern detected" },
+ { 0x000e0000, "Tx FIFO parity error" },
+ { 0x0001c000, "Rx FIFO parity error" },
+ { F_TXFIFO_UNDERRUN, "Tx FIFO underrun" },
+ { F_RXFIFO_OVERFLOW, "Rx FIFO overflow" },
+ { 0x00000f00, "XAUI SERDES BIST error" },
+ { 0x000000f0, "XAUI SERDES receive low signal change" },
+ { F_XAUIPCSCTCERR, "XAUI PCS CTC FIFO error" },
+ { F_XAUIPCSALIGNCHANGE, "XAUI PCS alignment change" },
+ { F_RGMIILINKSTSCHANGE, "RGMII link status change" },
+ { F_XGM_INT, "XGM Core embedded interrupt (2nd level)" },
+ { 0 }
+ };
static const struct intr_info ncsi_xgmac0_int_cause = {
.name = "NCSI_XGMAC0_INT_CAUSE",
.cause_reg = A_NCSI_XGMAC0_INT_CAUSE,
.enable_reg = A_NCSI_XGMAC0_INT_ENABLE,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = ncsi_xgmac0_int_cause_details,
.actions = NULL,
};
bool fatal = false;
@@ -6346,32 +7600,71 @@ static bool ncsi_intr_handler(struct adapter *adap, int arg, int flags)
*/
static bool mac_intr_handler(struct adapter *adap, int port, int flags)
{
+ static const struct intr_details mac_int_cause_cmn_details[] = {
+ { 0x3fffc0, "HSS PLL lock error " },
+ { F_FLOCK_ASSERTED, "frequency lock coming out of DPLL sub-block is asserted" },
+ { F_FLOCK_LOST, "frequency lock coming out of DPLL sub-blocki is lost." },
+ { F_PHASE_LOCK_ASSERTED, "PHASE LOCK from DPLL sub-block is asserted" },
+ { F_PHASE_LOCK_LOST, "PHASE LOCK from DPLL sub-block is lost." },
+ { F_LOCK_ASSERTED, "Lock from frac_n PLL inside t7_clk module is asserted" },
+ { F_LOCK_LOST, "Lock from frac_n PLL inside t7_clk module is lost " },
+ { 0 }
+ };
static const struct intr_info mac_int_cause_cmn = {
.name = "MAC_INT_CAUSE_CMN",
.cause_reg = A_MAC_INT_CAUSE_CMN,
.enable_reg = A_MAC_INT_EN_CMN,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = mac_int_cause_cmn_details,
.actions = NULL,
};
+ static const struct intr_details mac_perr_int_cause_mtip_details[] = {
+ { F_PERR_MAC0_TX, "MTIP MAC TX memory for MAC 0 (the 200G MAC for port 0)" },
+ { F_PERR_MAC1_TX, "MTIP MAC TX memory for MAC 1 (the 200G MAC for port 1)" },
+ { F_PERR_MAC2_TX, "MTIP MAC TX memory for MAC 2 (the 10-100G MAC for port 0)" },
+ { F_PERR_MAC3_TX, "MTIP MAC TX memory for MAC 3 (the 10-100G MAC for port 1)" },
+ { F_PERR_MAC4_TX, "MTIP MAC TX memory for MAC 4 (the 10-100G MAC for port 2)" },
+ { F_PERR_MAC5_TX, "MTIP MAC TX memory for MAC 5 (the 10-100G MAC for port 3)" },
+ { F_PERR_MAC0_RX, "MTIP MAC RX memory for MAC 0 (the 200G MAC for port 0)" },
+ { F_PERR_MAC1_RX, "MTIP MAC RX memory for MAC 1 (the 200G MAC for port 1)" },
+ { F_PERR_MAC2_RX, "MTIP MAC RX memory for MAC 2 (the 10-100G MAC for port 0)" },
+ { F_PERR_MAC3_RX, "MTIP MAC RX memory for MAC 3 (the 10-100G MAC for port 1)" },
+ { F_PERR_MAC4_RX, "MTIP MAC RX memory for MAC 4 (the 10-100G MAC for port 2)" },
+ { F_PERR_MAC5_RX, "MTIP MAC RX memory for MAC 5 (the 10-100G MAC for port 3)" },
+ { F_PERR_MAC_STAT_RX, "MTIP MAC RX statistics memory (1 for all 4 10-100G MACs)" },
+ { F_PERR_MAC_STAT_TX, "MTIP MAC TX statistics memory (1 for all 4 10-100G MACs)" },
+ { F_PERR_MAC_STAT_CAP, "MTIP MAC stat capture memory (1 for all 4 100G MACs)" },
+ { 0 }
+ };
static const struct intr_info mac_perr_cause_mtip = {
.name = "MAC_PERR_INT_CAUSE_MTIP",
.cause_reg = A_MAC_PERR_INT_CAUSE_MTIP,
.enable_reg = A_MAC_PERR_INT_EN_MTIP,
.fatal = 0xffffffff,
.flags = IHF_FATAL_IFF_ENABLED | IHF_IGNORE_IF_DISABLED,
- .details = NULL,
+ .details = mac_perr_int_cause_mtip_details,
.actions = NULL,
};
- static const struct intr_info mac_cerr_cause_mtip = {
- .name = "MAC_CERR_INT_CAUSE_MTIP",
- .cause_reg = A_MAC_CERR_INT_CAUSE_MTIP,
- .enable_reg = A_MAC_CERR_INT_EN_MTIP,
- .fatal = 0,
- .flags = 0,
- .details = NULL,
- .actions = NULL,
+ static const struct intr_details ios_intr_cause_quad0_details[] = {
+ { F_Q0_MAILBOX_INT_ASSERT, "Etopus Quad0 Mailbox interrupt cause" },
+ { 0x00f00000, "Etopus Quad0 training failure" },
+ { 0x000f0000, "Etopus Quad0 training complete" },
+ { 0x0000f000, "Etopus Quad0 AN TX interrupt" },
+ { 0x00000f00, "Etopus Quad0 signal detect assertion" },
+ { 0x000000f0, "Etopus Quad0 CDR LOL assertion" },
+ { 0x0000000f, "Etopus Quad0 LOS signal assertion" },
+ { 0 }
+ };
+ static const struct intr_details ios_intr_cause_quad1_details[] = {
+ { F_Q1_MAILBOX_INT_ASSERT, "Etopus Quad1 Mailbox interrupt cause" },
+ { 0x00f00000, "Etopus Quad1 training failure" },
+ { 0x000f0000, "Etopus Quad1 training complete" },
+ { 0x0000f000, "Etopus Quad1 AN TX interrupt" },
+ { 0x00000f00, "Etopus Quad1 signal detect assertion" },
+ { 0x000000f0, "Etopus Quad1 CDR LOL assertion" },
+ { 0x0000000f, "Etopus Quad1 LOS signal assertion" },
+ { 0 }
};
static const struct intr_info mac_ios_int_cause_quad0 = {
.name = "MAC_IOS_INTR_CAUSE_QUAD0",
@@ -6379,7 +7672,7 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags)
.enable_reg = A_MAC_IOS_INTR_EN_QUAD0,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = ios_intr_cause_quad0_details,
.actions = NULL,
};
static const struct intr_info mac_ios_int_cause_quad1 = {
@@ -6388,7 +7681,7 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags)
.enable_reg = A_MAC_IOS_INTR_EN_QUAD1,
.fatal = 0,
.flags = 0,
- .details = NULL,
+ .details = ios_intr_cause_quad1_details,
.actions = NULL,
};
static const struct intr_details mac_intr_details[] = {
@@ -6396,6 +7689,33 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags)
{ F_RXFIFO_PRTY_ERR, "MAC Rx FIFO parity error" },
{ 0 }
};
+ static const struct intr_details t7_mac_int_cause_details[] = {
+ { F_MAC2MPS_PERR_CAUSE, "MPS2MAC Data parity error per port" },
+ { F_MAC_PPS_INT_CAUSE, "One second interrupt based on PTP timer" },
+ { F_MAC_TX_TS_AVAIL_INT_CAUSE,
+ "Time stamp is available for the last IEEE 1588 event frame" },
+ { F_MAC_PATDETWAKE_INT_CAUSE, "Wake up pattern match packet received" },
+ { F_MAC_MAGIC_WAKE_INT_CAUSE, "Magic packet received" },
+ { F_MAC_SIGDETCHG_INT_CAUSE, "Signal Detect Change" },
+ { F_MAC_PCS_LINK_GOOD_CAUSE, "PCS link good (xaui pcsr or 1g)" },
+ { F_MAC_PCS_LINK_FAIL_CAUSE, "PCS Failure (xaui pcsr or 1g)" },
+ { F_RXFIFOOVERFLOW, "RX Fifo Over flow error" },
+ { F_MAC_REM_FAULT_INT_CAUSE, "Remote fault received by XGMAC" },
+ { F_MAC_LOC_FAULT_INT_CAUSE, "Local fault received by XGMAC" },
+ { F_MAC_LINK_DOWN_INT_CAUSE, "Link is down" },
+ { F_MAC_LINK_UP_INT_CAUSE, "Link is up" },
+ { F_MAC_AN_DONE_INT_CAUSE, "Autonegotiation complete" },
+ { F_MAC_AN_PGRD_INT_CAUSE, "An page received" },
+ { F_MAC_TXFIFO_ERR_INT_CAUSE, "Tx FIFO parity error" },
+ { F_MAC_RXFIFO_ERR_INT_CAUSE, "Rx FIFO parity error" },
+ { 0 }
+ };
+ static const struct intr_details mac_perr_int_cause_details[] = {
+ { F_T6_PERR_PKT_RAM, "WoL packet data memory" },
+ { F_T6_PERR_MASK_RAM, "WoL mask memory" },
+ { F_T6_PERR_CRC_RAM, "WoL CRC memory" },
+ { 0 }
+ };
char name[32];
struct intr_info ii;
bool fatal = false;
@@ -6428,7 +7748,7 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags)
ii.enable_reg = T7_PORT_REG(port, A_T7_MAC_PORT_INT_EN);
ii.fatal = 0xffffffff;
ii.flags = IHF_FATAL_IFF_ENABLED;
- ii.details = NULL;
+ ii.details = t7_mac_int_cause_details;
ii.actions = NULL;
}
fatal |= t4_handle_intr(adap, &ii, 0, flags);
@@ -6443,7 +7763,7 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags)
ii.enable_reg = T7_PORT_REG(port, A_T7_MAC_PORT_PERR_INT_EN);
ii.fatal = 0xffffffff;
ii.flags = IHF_FATAL_IFF_ENABLED;
- ii.details = NULL;
+ ii.details = mac_perr_int_cause_details;
ii.actions = NULL;
} else {
ii.name = &name[0];
@@ -6484,7 +7804,6 @@ static bool mac_intr_handler(struct adapter *adap, int port, int flags)
MPASS(chip_id(adap) >= CHELSIO_T7);
fatal |= t4_handle_intr(adap, &mac_int_cause_cmn, 0, flags);
fatal |= t4_handle_intr(adap, &mac_perr_cause_mtip, 0, flags);
- fatal |= t4_handle_intr(adap, &mac_cerr_cause_mtip, 0, flags);
fatal |= t4_handle_intr(adap, &mac_ios_int_cause_quad0, 0, flags);
fatal |= t4_handle_intr(adap, &mac_ios_int_cause_quad1, 0, flags);
@@ -6506,28 +7825,40 @@ static bool pl_timeout_status(struct adapter *adap, int arg, int flags)
static bool plpl_intr_handler(struct adapter *adap, int arg, int flags)
{
static const struct intr_details plpl_int_cause_fields[] = {
+ { F_FATALPERR, "Fatal parity error" },
+ { F_PERRVFID, "VFID_MAP parity error" },
+ { 0 }
+ };
+ static const struct intr_details t5_plpl_int_cause_fields[] = {
{ F_PL_BUSPERR, "Bus parity error" },
{ F_FATALPERR, "Fatal parity error" },
{ F_INVALIDACCESS, "Global reserved memory access" },
{ F_TIMEOUT, "Bus timeout" },
{ F_PLERR, "Module reserved access" },
- { F_PERRVFID, "VFID_MAP parity error" },
{ 0 }
};
static const struct intr_action plpl_int_cause_actions[] = {
{ F_TIMEOUT, -1, pl_timeout_status },
{ 0 },
};
- static const struct intr_info plpl_int_cause = {
+ struct intr_info plpl_int_cause = {
.name = "PL_PL_INT_CAUSE",
.cause_reg = A_PL_PL_INT_CAUSE,
.enable_reg = A_PL_PL_INT_ENABLE,
- .fatal = F_FATALPERR | F_PERRVFID,
- .flags = IHF_FATAL_IFF_ENABLED | IHF_IGNORE_IF_DISABLED,
- .details = plpl_int_cause_fields,
- .actions = plpl_int_cause_actions,
+ .fatal = F_FATALPERR,
+ .flags = IHF_FATAL_IFF_ENABLED,
+ .details = NULL,
+ .actions = NULL,
};
+ if (is_t4(adap)) {
+ plpl_int_cause.fatal |= F_PERRVFID;
+ plpl_int_cause.details = plpl_int_cause_fields;
+ } else {
+ plpl_int_cause.fatal |= F_INVALIDACCESS;
+ plpl_int_cause.details = t5_plpl_int_cause_fields;
+ plpl_int_cause.actions = plpl_int_cause_actions;
+ }
return (t4_handle_intr(adap, &plpl_int_cause, 0, flags));
}
@@ -6587,7 +7918,7 @@ static bool hma_intr_handler(struct adapter *adap, int idx, int flags)
{ F_RTF_INT_CAUSE, "Region translation fault" },
{ F_PCIEMST_INT_CAUSE, "PCIe master access error" },
{ F_MAMST_INT_CAUSE, "MA master access error" },
- { 1, "FIFO parity error" },
+ { F_PERR_INT_CAUSE, "FIFO parity error" },
{ 0 }
};
static const struct intr_info hma_int_cause = {
@@ -6682,15 +8013,6 @@ static bool gcache_intr_handler(struct adapter *adap, int idx, int flags)
{ F_ILLADDRACCESS0_INT_CAUSE, "GC0 illegal address access" },
{ 0 }
};
- static const struct intr_info gcache_perr_cause = {
- .name = "GCACHE_PAR_CAUSE",
- .cause_reg = A_GCACHE_PAR_CAUSE,
- .enable_reg = A_GCACHE_PAR_ENABLE,
- .fatal = 0xffffffff,
- .flags = IHF_FATAL_IFF_ENABLED,
- .details = NULL,
- .actions = NULL,
- };
static const struct intr_info gcache_int_cause = {
.name = "GCACHE_INT_CAUSE",
.cause_reg = A_GCACHE_INT_CAUSE,
@@ -6700,12 +8022,7 @@ static bool gcache_intr_handler(struct adapter *adap, int idx, int flags)
.details = gcache_int_cause_fields,
.actions = NULL,
};
- bool fatal = false;
-
- fatal |= t4_handle_intr(adap, &gcache_int_cause, 0, flags);
- fatal |= t4_handle_intr(adap, &gcache_perr_cause, 0, flags);
-
- return (fatal);
+ return (t4_handle_intr(adap, &gcache_int_cause, 0, flags));
}
/*
@@ -6713,67 +8030,218 @@ static bool gcache_intr_handler(struct adapter *adap, int idx, int flags)
*/
static bool arm_intr_handler(struct adapter *adap, int idx, int flags)
{
+ static const struct intr_details arm_perr_int_cause0_details[] = {
+ { F_INIC_WRDATA_FIFO_PERR, "INT CAUSE for INIC Write Data Fifo Parity Error" },
+ { F_INIC_RDATA_FIFO_PERR, "INT CAUSE for INIC Read Data Fifo Parity Error" },
+ { F_MSI_MEM_PERR, "INT CAUSE for MSI Memory Parity Error" },
+ { 0x18000000, "INT CAUSE for ARM Doorbell SRAM Parity Error" },
+ { F_EMMC_FIFOPARINT, "INT CAUSE for EMMC Fifo Parity Interrupt" },
+ { F_ICB_RAM_PERR, "INT CAUSE for ICB SRAM Parity Error" },
+ { F_MESS2AXI4_WRFIFO_PERR, "INT CAUSE for Message2AXI4 Write FIFO Parity Error" },
+ { F_RC_WFIFO_OUTPERR, "INT CAUSE for AXI2RC Write FIFO Parity Error" },
+ { 0x00600000, "INT CAUSE for AXI2RC SRAM Parity Error" },
+ { F_MSI_FIFO_PAR_ERR, "INT CAUSE for APB2MSI FIFO Parity Error" },
+ { F_INIC2MA_INTFPERR, "INT CAUSE for INIC to MA Interface Parity Error" },
+ { F_RDATAFIFO0_PERR, "INT CAUSE for AXI2MA M0 Read Data Fifo Parity Error" },
+ { F_RDATAFIFO1_PERR, "INT CAUSE for AXI2MA M1 Read Data Fifo Parity Error" },
+ { F_WRDATAFIFO0_PERR, "INT CAUSE for AXI2MA M0 Write Data Fifo Parity Error" },
+ { F_WRDATAFIFO1_PERR, "INT CAUSE for AXI2MA M1 Write Data Fifo Parity Error" },
+ { F_WR512DATAFIFO0_PERR,
+ "INT CAUSE for AXI2MA M0 Write Data 512b Fifo Parity Error" },
+ { F_WR512DATAFIFO1_PERR,
+ "INT CAUSE for AXI2MA M1 Write Data 512b Fifo Parity Error" },
+ { F_ROBUFF_PARERR3, "INT CAUSE for Reorder Buffer Parity Error" },
+ { F_ROBUFF_PARERR2, "INT CAUSE for Reorder Buffer Parity Error" },
+ { F_ROBUFF_PARERR1, "INT CAUSE for Reorder Buffer Parity Error" },
+ { F_ROBUFF_PARERR0, "INT CAUSE for Reorder Buffer Parity Error" },
+ { F_MA2AXI_REQDATAPARERR, "INT CAUSE for MA2AXI Request Data Parity Error" },
+ { F_MA2AXI_REQCTLPARERR, "INT CAUSE for MA2AXI Request Control Parity Error" },
+ { F_MA_RSPPERR, "INT CAUSE for MA Response Parity Error" },
+ { F_PCIE2MA_REQCTLPARERR, "INT CAUSE for PCIe to MA Control Parity Error" },
+ { F_PCIE2MA_REQDATAPARERR, "INT CAUSE for PCIe to MA Data Parity Error" },
+ { F_INIC2MA_REQCTLPARERR, "INT CAUSE for INIC to MA Control Parity Error" },
+ { F_INIC2MA_REQDATAPARERR, "INT CAUSE for INIC to MA Data Parity Error" },
+ { F_MA_RSPUE, "INT CAUSE for MA Response Uncorrectable Error" },
+ { F_APB2PL_RSPDATAPERR, "INT CAUSE for APB2PL Response Data Parity Error" },
+ { 0 }
+ };
static const struct intr_info arm_perr_cause0 = {
.name = "ARM_PERR_INT_CAUSE0",
.cause_reg = A_ARM_PERR_INT_CAUSE0,
.enable_reg = A_ARM_PERR_INT_ENB0,
.fatal = 0xffffffff,
.flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = arm_perr_int_cause0_details,
.actions = NULL,
};
+ static const struct intr_details arm_perr_int_cause1_details[] = {
+ { F_ARWFIFO0_PERR, "AXI2MA M0 Read-Write FIFO Parity Error" },
+ { F_ARWFIFO1_PERR, "AXI2MA M1 Read-Write FIFO Parity Error" },
+ { F_ARWIDFIFO0_PERR, "AXI2MA M0 Read-Write ID FIFO Parity Error" },
+ { F_ARWIDFIFO1_PERR, "AXI2MA M1 Read-Write ID FIFO Parity Error" },
+ { F_ARIDFIFO0_PERR, "AXI2MA M0 Read FIFO Parity Error" },
+ { F_ARIDFIFO1_PERR, "AXI2MA M1 Read FIFO Parity Error" },
+ { F_RRSPADDR_FIFO0_PERR, "AXI2MA M0 Read Response Address FIFO Parity Error" },
+ { F_RRSPADDR_FIFO1_PERR, "AXI2MA M1 Read Response Address FIFO Parity Error" },
+ { F_WRSTRB_FIFO0_PERR, "AXI2MA M0 Write Strobe FIFO Parity Error" },
+ { F_WRSTRB_FIFO1_PERR, "AXI2MA M1 Write Strobe FIFO Parity Error" },
+ { F_MA2AXI_RSPDATAPARERR, "MA2AXI Response FIFO Parity Error" },
+ { F_MA2AXI_DATA_PAR_ERR, "MA2AXI Write Data FIFO Parity Error" },
+ { F_MA2AXI_WR_ORD_FIFO_PARERR, "MA2AXI Ordered Write Data FIFO Parity Error" },
+ { F_NVME_DB_EMU_TRACKER_FIFO_PERR, "NVMe DB Emulation Tracker FIFO Parity Error" },
+ { F_NVME_DB_EMU_QUEUE_AW_ADDR_FIFO_PERR,
+ "NVMe DB Emulation Queue AW Addr Parity Error" },
+ { F_NVME_DB_EMU_INTERRUPT_OFFSET_FIFO_PERR,
+ "NVMe DB Emulation Interrupt Offset FIFO Parity Error" },
+ { F_NVME_DB_EMU_ID_FIFO0_PERR, "NVMe DB Emulation ID FIFO0 Parity Error" },
+ { F_NVME_DB_EMU_ID_FIFO1_PERR, "NVMe DB Emulation ID FIFO1 Parity Error" },
+ { F_RC_ARWFIFO_PERR, "AXI2RC Read-Write FIFO Parity Error" },
+ { F_RC_ARIDBURSTADDRFIFO_PERR,
+ "AXI2RC Read ID, Burst and Address FIFO Parity Error" },
+ { F_RC_CFG_FIFO_PERR, "AXI2RC Config FIFO Parity Error" },
+ { F_RC_RSPFIFO_PERR, "AXI2RC Response Parity Error" },
+ { F_INIC_ARIDFIFO_PERR, "CCI2INIC Read ID FIFO Parity Error" },
+ { F_INIC_ARWFIFO_PERR, "CCI2INIC Read-Write FIFO ontrol Parity Error" },
+ { F_AXI2MA_128_RD_ADDR_SIZE_FIFO_PERR,
+ "AXI2MA(CCI2INIC) Read Address Size FIFO Parity Error" },
+ { F_AXI2RC_128_RD_ADDR_SIZE_FIFO_PERR,
+ "AXI2RC Read Address Size FIFO Parity Error" },
+ { F_ARM_MA_512B_RD_ADDR_SIZE_FIFO0_PERR,
+ "ARM_MA_512b Read Address Size FIFO0 Parity Error" },
+ { F_ARM_MA_512B_RD_ADDR_SIZE_FIFO1_PERR,
+ "ARM_MA_512b Read Address Size FIFO1 Parity Error" },
+ { F_ARM_MA_512B_ARB_FIFO_PERR, "ARM_MA_512b Arbiter FIFO Parity Error" },
+ { F_PCIE_INIC_MA_ARB_FIFO_PERR, "PCIe-INIC Arbiter FIFO Parity Error" },
+ { F_PCIE_INIC_ARB_RSPPERR, "PCIe-INIC Arbiter Response Parity Error" },
+ { F_ITE_CACHE_PERR, "GIC500 ITE Cache SRAM Parity Error" },
+ { 0 }
+ };
static const struct intr_info arm_perr_cause1 = {
.name = "ARM_PERR_INT_CAUSE1",
.cause_reg = A_ARM_PERR_INT_CAUSE1,
.enable_reg = A_ARM_PERR_INT_ENB1,
.fatal = 0xffffffff,
.flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = arm_perr_int_cause1_details,
.actions = NULL,
};
+ static const struct intr_details arm_perr_int_cause2_details[] = {
+ { F_INIC_WSTRB_FIFO_PERR, "AXI2MA_128 INIC Write Strobe FIFO Parity Error" },
+ { F_INIC_BID_FIFO_PERR, "AXI2MA_128 INIC bID FIFO Parity Error" },
+ { F_CC_SRAM_PKA_PERR, "CryptoCell ram_pka_wrapper FIFO Parity Error" },
+ { F_CC_SRAM_SEC_PERR, "CryptoCell sec_sram_wrapper FIFO Parity Error" },
+ { F_MESS2AXI4_PARERR, "Message2AXI4 IBQ I/P Interface Parity Error" },
+ { F_CCI2INIC_INTF_PARERR, "CCI2INIC Response Interface Parity Error" },
+ { 0 }
+ };
static const struct intr_info arm_perr_cause2 = {
.name = "ARM_PERR_INT_CAUSE2",
.cause_reg = A_ARM_PERR_INT_CAUSE2,
.enable_reg = A_ARM_PERR_INT_ENB2,
.fatal = 0xffffffff,
.flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = arm_perr_int_cause2_details,
.actions = NULL,
};
+ static const struct intr_details arm_cerr_int_cause0_details[] = {
+ { F_WRDATA_FIFO0_CERR, "AXI2MA M0 Write Data FIFO Correctable Error" },
+ { F_WRDATA_FIFO1_CERR, "AXI2MA M1 Write Data FIFO Correctable Error" },
+ { F_WR512DATAFIFO0_CERR, "AXI2MA M0 Write Data 512b FIFO Correctable Error" },
+ { F_WR512DATAFIFO1_CERR, "AXI2MA M1 Write Data 512b FIFO Correctable Error" },
+ { F_RDATAFIFO0_CERR, "AXI2MA M0 Read Data FIFO Correctable Error" },
+ { F_RDATAFIFO1_CERR, "AXI2MA M1 Read Data FIFO Correctable Error" },
+ { F_ROBUFF_CORERR0, "Reorder Buffer Correctable Error" },
+ { F_ROBUFF_CORERR1, "Reorder Buffer Correctable Error" },
+ { F_ROBUFF_CORERR2, "Reorder Buffer Correctable Error" },
+ { F_ROBUFF_CORERR3, "Reorder Buffer Correctable Error" },
+ { F_MA2AXI_RSPDATACORERR, "MA2AXI Response FIFO Correctable Error" },
+ { 0x00180000, "AXI2RC SRAM Correctable Error" },
+ { F_RC_WFIFO_OUTCERR, "AXI2RC Write FIFO Correctable Error" },
+ { F_RC_RSPFIFO_CERR, "AXI2RC Response Correctable Error" },
+ { F_MSI_MEM_CERR, "MSI Memory FIFO Correctable Error" },
+ { F_INIC_WRDATA_FIFO_CERR, "INIC Write Data FIFO Correctable Error" },
+ { F_INIC_RDATAFIFO_CERR, "INIC Read Data FIFO Correctable Error" },
+ { 0x00003000, "ARM Doorbell SRAM Correctable Error" },
+ { F_ICB_RAM_CERR, "ICB SRAM Parity Error" },
+ { F_CC_SRAM_PKA_CERR, "CryptoCell ram_pka_wrapper FIFO Correctable Error" },
+ { F_CC_SRAM_SEC_CERR, "CryptoCell sec_sram_wrapper FIFO Correctable Error" },
+ { 0 }
+ };
static const struct intr_info arm_cerr_cause0 = {
- .name = "ARM_CERR_INT_CAUSE",
+ .name = "ARM_CERR_INT_CAUSE0",
.cause_reg = A_ARM_CERR_INT_CAUSE0,
.enable_reg = A_ARM_CERR_INT_ENB0,
.fatal = 0,
.flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = arm_cerr_int_cause0_details,
.actions = NULL,
};
+ static const struct intr_details arm_err_int_cause0_details[] = {
+ { F_STRB0_ERROR, "Strobe Error from AXI2MA 0" },
+ { F_STRB1_ERROR, "Strobe Error from AXI2MA 1" },
+ { F_PCIE_INIC_MA_ARB_INV_RSP_TAG, "Invalid Response Tag for PCIE-INIc MA ARB" },
+ { F_ERROR0_NOCMD_DATA, "AXI2MA 0 No Command Data Error" },
+ { F_ERROR1_NOCMD_DATA, "AXI2MA 1 No Command Data Error" },
+ { F_INIC_STRB_ERROR, "AXI2MA_128b INIC Strobe Error" },
+ { 0 }
+ };
static const struct intr_info arm_err_cause0 = {
- .name = "ARM_ERR_INT_CAUSE",
+ .name = "ARM_ERR_INT_CAUSE0",
.cause_reg = A_ARM_ERR_INT_CAUSE0,
.enable_reg = A_ARM_ERR_INT_ENB0,
.fatal = 0,
.flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = arm_err_int_cause0_details,
.actions = NULL,
};
+
+ static const struct intr_details arm_peripheral_int_cause_details[] = {
+ { F_TIMER_INT, "TIMER_INT" },
+ { F_NVME_INT, "NVME_INT" },
+ { F_EMMC_WAKEUP_INT, "EMMC_WAKEUP_INT" },
+ { F_EMMC_INT, "EMMC_INT" },
+ { F_USB_MC_INT, "USB_MC_INT" },
+ { F_USB_DMA_INT, "USB_DMA_INT" },
+ { 0 }
+ };
static const struct intr_info arm_periph_cause = {
.name = "ARM_PERIPHERAL_INT_CAUSE",
.cause_reg = A_ARM_PERIPHERAL_INT_CAUSE,
.enable_reg = A_ARM_PERIPHERAL_INT_ENB,
.fatal = 0,
.flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = arm_peripheral_int_cause_details,
.actions = NULL,
};
+ static const struct intr_details arm_arm_uart_int_cause_details[] = {
+ { F_RX_FIFO_NOT_EMPTY, "intcause for uart rx fifo" },
+ { F_TX_FIFO_EMPTY, "intcause for uart tx fifo" },
+ { 0 }
+ };
+ static const struct intr_info arm_uart_cause = {
+ .name = "ARM_ARM_UART_INT_CAUSE",
+ .cause_reg = A_ARM_ARM_UART_INT_CAUSE,
+ .enable_reg = A_ARM_ARM_UART_INT_EN,
+ .fatal = 0,
+ .flags = IHF_FATAL_IFF_ENABLED,
+ .details = arm_arm_uart_int_cause_details,
+ .actions = NULL,
+ };
+ static const struct intr_details arm_nvme_db_emu_int_cause_details[] = {
+ { F_INVALID_BRESP, "Invalid CCI Write Response" },
+ { F_DATA_LEN_OF,
+ "Incorrect Write Request to be written to incorrect Devices/Regions" },
+ { F_INVALID_EMU_ADDR, "Invalid Emulation Address Range Configuration" },
+ { F_INVALID_AXI_ADDR_CFG, "Invalid AXI Address Configuration" },
+ { 0 }
+ };
static const struct intr_info arm_nvme_db_emu_cause = {
.name = "ARM_NVME_DB_EMU_INT_CAUSE",
.cause_reg = A_ARM_NVME_DB_EMU_INT_CAUSE,
.enable_reg = A_ARM_NVME_DB_EMU_INT_ENABLE,
.fatal = 0,
.flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED,
- .details = NULL,
+ .details = arm_nvme_db_emu_int_cause_details,
.actions = NULL,
};
bool fatal = false;
@@ -6785,12 +8253,13 @@ static bool arm_intr_handler(struct adapter *adap, int idx, int flags)
fatal |= t4_handle_intr(adap, &arm_err_cause0, 0, flags);
fatal |= t4_handle_intr(adap, &arm_periph_cause, 0, flags);
fatal |= t4_handle_intr(adap, &arm_nvme_db_emu_cause, 0, flags);
+ fatal |= t4_handle_intr(adap, &arm_uart_cause, 0, flags);
return (fatal);
}
static inline uint32_t
-get_perr_ucause(struct adapter *sc, const struct intr_info *ii)
+get_ucause(struct adapter *sc, const struct intr_info *ii)
{
uint32_t cause;
@@ -6977,7 +8446,8 @@ bool t4_slow_intr_handler(struct adapter *adap, int flags)
.cause_reg = A_PL_PERR_CAUSE,
.enable_reg = A_PL_PERR_ENABLE,
.fatal = 0xffffffff,
- .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED,
+ .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED |
+ IHF_CLR_DELAYED,
.details = pl_int_cause_fields,
.actions = NULL,
};
@@ -7117,7 +8587,8 @@ bool t4_slow_intr_handler(struct adapter *adap, int flags)
.cause_reg = A_PL_PERR_CAUSE,
.enable_reg = A_PL_PERR_ENABLE,
.fatal = 0xffffffff,
- .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED,
+ .flags = IHF_IGNORE_IF_DISABLED | IHF_FATAL_IFF_ENABLED |
+ IHF_CLR_DELAYED,
.details = t7_pl_perr_cause_fields,
.actions = NULL,
};
@@ -7125,23 +8596,19 @@ bool t4_slow_intr_handler(struct adapter *adap, int flags)
uint32_t perr;
if (chip_id(adap) < CHELSIO_T7) {
- perr = get_perr_ucause(adap, &pl_perr_cause);
- fatal |= t4_handle_intr(adap, &pl_perr_cause, 0,
- flags & ~(IHF_CLR_ALL_SET | IHF_CLR_ALL_UNIGNORED));
+ perr = get_ucause(adap, &pl_perr_cause);
+ fatal |= t4_handle_intr(adap, &pl_perr_cause, 0, flags);
fatal |= t4_handle_intr(adap, &pl_int_cause,
t4_perr_to_ic(adap, perr), flags);
- t4_write_reg(adap, pl_perr_cause.cause_reg, perr);
- (void)t4_read_reg(adap, pl_perr_cause.cause_reg);
+ clear_int_cause_reg(adap, &pl_perr_cause, flags);
} else {
- perr = get_perr_ucause(adap, &t7_pl_perr_cause);
- fatal |= t4_handle_intr(adap, &t7_pl_perr_cause, 0,
- flags & ~(IHF_CLR_ALL_SET | IHF_CLR_ALL_UNIGNORED));
+ perr = get_ucause(adap, &t7_pl_perr_cause);
+ fatal |= t4_handle_intr(adap, &t7_pl_perr_cause, 0, flags);
fatal |= t4_handle_intr(adap, &t7_pl_int_cause,
t7_perr_to_ic1(perr), flags);
fatal |= t4_handle_intr(adap, &t7_pl_int_cause2,
t7_perr_to_ic2(perr), flags);
- t4_write_reg(adap, t7_pl_perr_cause.cause_reg, perr);
- (void)t4_read_reg(adap, t7_pl_perr_cause.cause_reg);
+ clear_int_cause_reg(adap, &t7_pl_perr_cause, flags);
}
return (fatal);
}
diff --git a/sys/dev/cxgbe/crypto/t7_kern_tls.c b/sys/dev/cxgbe/crypto/t7_kern_tls.c
index b6078b9b53b6..2cde8ff28794 100644
--- a/sys/dev/cxgbe/crypto/t7_kern_tls.c
+++ b/sys/dev/cxgbe/crypto/t7_kern_tls.c
@@ -1557,7 +1557,7 @@ ktls_write_tls_wr(struct tlspcb *tlsp, struct sge_txq *txq,
V_T7_ULP_TXPKT_CHANNELID(tlsp->vi->pi->port_id) |
V_ULP_TXPKT_DEST(0) |
V_ULP_TXPKT_CMDMORE(request_ghash ? 1 : 0) |
- V_ULP_TXPKT_FID(txq->eq.cntxt_id) | V_ULP_TXPKT_RO(1));
+ V_ULP_TXPKT_FID(txq->eq.iqid) | V_ULP_TXPKT_RO(1));
txpkt->len = htobe32(howmany(txpkt_lens[0], 16));
/* ULPTX_IDATA sub-command */
@@ -1949,7 +1949,7 @@ ktls_write_tls_wr(struct tlspcb *tlsp, struct sge_txq *txq,
V_ULP_TXPKT_DATAMODIFY(0) |
V_T7_ULP_TXPKT_CHANNELID(tlsp->vi->pi->port_id) |
V_ULP_TXPKT_DEST(0) |
- V_ULP_TXPKT_FID(txq->eq.cntxt_id) | V_ULP_TXPKT_RO(1));
+ V_ULP_TXPKT_FID(txq->eq.iqid) | V_ULP_TXPKT_RO(1));
txpkt->len = htobe32(howmany(txpkt_lens[1], 16));
/* ULPTX_IDATA sub-command */
diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c
index 07906dac00a8..573c8f71b084 100644
--- a/sys/dev/cxgbe/t4_main.c
+++ b/sys/dev/cxgbe/t4_main.c
@@ -12576,7 +12576,7 @@ get_sge_context(struct adapter *sc, int mem_id, uint32_t cid, int len,
goto done;
}
- if (sc->flags & FW_OK) {
+ if (sc->flags & FW_OK && !is_t7(sc)) {
rc = -t4_sge_ctxt_rd(sc, sc->mbox, cid, mem_id, data);
if (rc == 0)
goto done;
diff --git a/sys/dev/hwpmc/hwpmc_intel.c b/sys/dev/hwpmc/hwpmc_intel.c
index 942cadfae4cf..4c8d0cd2e2bd 100644
--- a/sys/dev/hwpmc/hwpmc_intel.c
+++ b/sys/dev/hwpmc/hwpmc_intel.c
@@ -266,6 +266,10 @@ pmc_intel_initialize(void)
cputype = PMC_CPU_INTEL_EMERALD_RAPIDS;
nclasses = 3;
break;
+ case 0x8F:
+ cputype = PMC_CPU_INTEL_SAPPHIRE_RAPIDS;
+ nclasses = 3;
+ break;
}
break;
}
diff --git a/sys/dev/ichiic/ig4_pci.c b/sys/dev/ichiic/ig4_pci.c
index 49036c6dabc9..52e072e8eae1 100644
--- a/sys/dev/ichiic/ig4_pci.c
+++ b/sys/dev/ichiic/ig4_pci.c
@@ -196,6 +196,12 @@ static int ig4iic_pci_detach(device_t dev);
#define PCI_CHIP_LUNARLAKE_M_I2C_1 0xa8798086
#define PCI_CHIP_LUNARLAKE_M_I2C_2 0xa87a8086
#define PCI_CHIP_LUNARLAKE_M_I2C_3 0xa87b8086
+#define PCI_CHIP_PANTHERLAKE_H_I2C_0 0xe4788086
+#define PCI_CHIP_PANTHERLAKE_H_I2C_1 0xe4798086
+#define PCI_CHIP_PANTHERLAKE_H_I2C_2 0xe4508086
+#define PCI_CHIP_PANTHERLAKE_H_I2C_3 0xe4518086
+#define PCI_CHIP_PANTHERLAKE_H_I2C_4 0xe47a8086
+#define PCI_CHIP_PANTHERLAKE_H_I2C_5 0xe47b8086
struct ig4iic_pci_device {
uint32_t devid;
@@ -336,6 +342,12 @@ static struct ig4iic_pci_device ig4iic_pci_devices[] = {
{ PCI_CHIP_LUNARLAKE_M_I2C_1, "Intel Lunar Lake-M I2C Controller-1", IG4_TIGERLAKE},
{ PCI_CHIP_LUNARLAKE_M_I2C_2, "Intel Lunar Lake-M I2C Controller-2", IG4_TIGERLAKE},
{ PCI_CHIP_LUNARLAKE_M_I2C_3, "Intel Lunar Lake-M I2C Controller-3", IG4_TIGERLAKE},
+ { PCI_CHIP_PANTHERLAKE_H_I2C_0, "Intel Panther Lake-H I2C Controller-0", IG4_TIGERLAKE},
+ { PCI_CHIP_PANTHERLAKE_H_I2C_1, "Intel Panther Lake-H I2C Controller-1", IG4_TIGERLAKE},
+ { PCI_CHIP_PANTHERLAKE_H_I2C_2, "Intel Panther Lake-H I2C Controller-2", IG4_TIGERLAKE},
+ { PCI_CHIP_PANTHERLAKE_H_I2C_3, "Intel Panther Lake-H I2C Controller-3", IG4_TIGERLAKE},
+ { PCI_CHIP_PANTHERLAKE_H_I2C_4, "Intel Panther Lake-H I2C Controller-4", IG4_TIGERLAKE},
+ { PCI_CHIP_PANTHERLAKE_H_I2C_5, "Intel Panther Lake-H I2C Controller-5", IG4_TIGERLAKE},
};
static int
diff --git a/sys/dev/ichsmb/ichsmb_pci.c b/sys/dev/ichsmb/ichsmb_pci.c
index 7f9409e4452c..7b85fe382a2d 100644
--- a/sys/dev/ichsmb/ichsmb_pci.c
+++ b/sys/dev/ichsmb/ichsmb_pci.c
@@ -119,6 +119,7 @@
#define ID_METEORLAKE 0x7e22
#define ID_METEORLAKE2 0x7f23
#define ID_METEORLAKE3 0xae22
+#define ID_PANTHERLAKE 0xe422
static const struct pci_device_table ichsmb_devices[] = {
{ PCI_DEV(PCI_VENDOR_INTEL, ID_82801AA),
@@ -280,6 +281,9 @@ static const struct pci_device_table ichsmb_devices[] = {
{ PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE3),
.driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
PCI_DESCR("Intel Meteor Lake SMBus controller") },
+ { PCI_DEV(PCI_VENDOR_INTEL, ID_PANTHERLAKE),
+ .driver_data = (uintptr_t)ICHSMB_FEATURE_BLOCK_BUFFER,
+ PCI_DESCR("Intel Panther Lake SMBus controller") },
};
/* Internal functions */
diff --git a/sys/dev/ntsync/linux_ntsync.c b/sys/dev/ntsync/linux_ntsync.c
new file mode 100644
index 000000000000..064e8c6aede9
--- /dev/null
+++ b/sys/dev/ntsync/linux_ntsync.c
@@ -0,0 +1,302 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2026 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ */
+
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include <dev/ntsync/ntsyncvar.h>
+
+#include <machine/../linux/linux.h>
+#include <machine/../linux/linux_proto.h>
+#include <compat/linux/linux_common.h>
+#include <compat/linux/linux_ioctl.h>
+#include <dev/ntsync/linux_ntsync.h>
+
+MODULE_DEPEND(linux_ntsync, linux, 1, 1, 1);
+MODULE_DEPEND(linux_ntsync, ntsync, 1, 1, 1);
+
+static linux_ioctl_function_t linux_ntsync_ioctl;
+static struct linux_ioctl_handler linux_ntsync_handler = {linux_ntsync_ioctl,
+ LNTSYNC_IOCTL_MIN, LNTSYNC_IOCTL_MAX};
+
+static int
+linux_ntsync_modevent(module_t mod __unused, int type, void *data __unused)
+{
+ int error;
+
+ error = 0;
+ switch (type) {
+ case MOD_LOAD:
+ error = linux_ioctl_register_handler(&linux_ntsync_handler);
+ if (error != 0) {
+ printf("linux_ntsync: cannot register ioctl handler, "
+ "error %d\n", error);
+ } else if (bootverbose)
+ printf("linux_ntsync\n");
+ break;
+
+ case MOD_UNLOAD:
+ linux_ioctl_unregister_handler(&linux_ntsync_handler);
+ break;
+
+ case MOD_SHUTDOWN:
+ break;
+
+ default:
+ error = EOPNOTSUPP;
+ }
+
+ return (error);
+}
+
+DEV_MODULE(linux_ntsync, linux_ntsync_modevent, NULL);
+MODULE_VERSION(linux_ntsync, 1);
+
+/* XXXKIB no translation of structs */
+static void
+ntsync_lsa_to_sa(struct ntsync_sem_args *sa,
+ const struct linux_ntsync_sem_args *lsa)
+{
+ memcpy(sa, lsa, sizeof(*sa));
+}
+
+static void
+ntsync_sa_to_lsa(struct linux_ntsync_sem_args *lsa,
+ const struct ntsync_sem_args *sa)
+{
+ memcpy(lsa, sa, sizeof(*lsa));
+}
+
+static void
+ntsync_lma_to_ma(struct ntsync_mutex_args *ma,
+ const struct linux_ntsync_mutex_args *lma)
+{
+ memcpy(ma, lma, sizeof(*ma));
+}
+
+static void
+ntsync_ma_to_lma(struct linux_ntsync_mutex_args *ma,
+ const struct ntsync_mutex_args *lma)
+{
+ memcpy(ma, lma, sizeof(*ma));
+}
+
+static void
+ntsync_lea_to_ea(struct ntsync_event_args *ea,
+ const struct linux_ntsync_event_args *lea)
+{
+ memcpy(ea, lea, sizeof(*ea));
+}
+
+static void
+ntsync_ea_to_lea(struct linux_ntsync_event_args *lea,
+ const struct ntsync_event_args *ea)
+{
+ memcpy(lea, ea, sizeof(*lea));
+}
+
+static void
+ntsync_lwa_to_wa(struct ntsync_wait_args *wa,
+ const struct linux_ntsync_wait_args *lwa)
+{
+ memcpy(wa, lwa, sizeof(*wa));
+}
+
+static void
+ntsync_wa_to_lwa(struct linux_ntsync_wait_args *lwa,
+ const struct ntsync_wait_args *wa)
+{
+ memcpy(lwa, wa, sizeof(*lwa));
+}
+
+static int
+linux_ntsync_cdev_ioctl(struct thread *td, u_long cmd, void *data,
+ struct file *fp)
+{
+ struct cdev *dev;
+ struct cdevsw *dsw;
+ struct vnode *vp;
+ struct file *fpop;
+ int error, ref;
+
+ if (fp->f_type != DTYPE_VNODE)
+ return (error = ENOIOCTL);
+
+ vp = fp->f_vnode;
+ if (vp->v_type != VCHR)
+ return (ENOIOCTL);
+ dev = vp->v_rdev;
+ dsw = dev_refthread(dev, &ref);
+ if (dsw == NULL)
+ return (ENXIO);
+ if (dsw != &ntsync_cdevsw) {
+ error = ENOIOCTL;
+ } else {
+ fpop = td->td_fpop;
+ td->td_fpop = fp;
+ error = dsw->d_ioctl(dev, cmd, data, 0, td);
+ td->td_fpop = fpop;
+ }
+ dev_relthread(dev, ref);
+ return (error);
+}
+
+static int
+linux_ntsync_ioctl(struct thread *td, struct linux_ioctl_args *args)
+{
+ struct file *fp;
+ void *data;
+ struct linux_ntsync_sem_args lsa;
+ struct linux_ntsync_mutex_args lma;
+ struct linux_ntsync_event_args lea;
+ struct linux_ntsync_wait_args lwa;
+ struct ntsync_sem_args sa;
+ struct ntsync_mutex_args ma;
+ struct ntsync_event_args ea;
+ struct ntsync_wait_args wa;
+ uint32_t val;
+ int error, error1, lcmd;
+ bool doco;
+
+ lcmd = args->cmd;
+ data = (void *)args->arg;
+
+ error = fget_cap(td, args->fd, &cap_no_rights, NULL, &fp, NULL);
+ if (error != 0)
+ goto out;
+
+ doco = false;
+ switch (lcmd) {
+ case LNTSYNC_IOC_CREATE_SEM:
+ error = copyin(data, &lsa, sizeof(lsa));
+ ntsync_lsa_to_sa(&sa, &lsa);
+ if (error == 0) {
+ error = linux_ntsync_cdev_ioctl(td,
+ NTSYNC_IOC_CREATE_SEM, &sa, fp);
+ }
+ break;
+ case LNTSYNC_IOC_CREATE_MUTEX:
+ error = copyin(data, &lma, sizeof(lma));
+ ntsync_lma_to_ma(&ma, &lma);
+ if (error == 0) {
+ error = linux_ntsync_cdev_ioctl(td,
+ NTSYNC_IOC_CREATE_MUTEX, &ma, fp);
+ }
+ break;
+ case LNTSYNC_IOC_CREATE_EVENT:
+ error = copyin(data, &lea, sizeof(lea));
+ ntsync_lea_to_ea(&ea, &lea);
+ if (error == 0) {
+ error = linux_ntsync_cdev_ioctl(td,
+ NTSYNC_IOC_CREATE_EVENT, &ea, fp);
+ }
+ break;
+ case LNTSYNC_IOC_WAIT_ANY:
+ error = copyin(data, &lwa, sizeof(lwa));
+ ntsync_lwa_to_wa(&wa, &lwa);
+ if (error == 0) {
+ error = linux_ntsync_cdev_ioctl(td,
+ NTSYNC_IOC_WAIT_ANY, &wa, fp);
+ if (error == 0 || error == EOWNERDEAD) {
+ ntsync_wa_to_lwa(&lwa, &wa);
+ error1 = copyout(&lwa, data, sizeof(lwa));
+ if (error == 0)
+ error = error1;
+ }
+ }
+ break;
+ case LNTSYNC_IOC_WAIT_ALL:
+ error = copyin(data, &lwa, sizeof(lwa));
+ ntsync_lwa_to_wa(&wa, &lwa);
+ if (error == 0) {
+ error = linux_ntsync_cdev_ioctl(td,
+ NTSYNC_IOC_WAIT_ALL, &wa, fp);
+ if (error == 0 || error == EOWNERDEAD) {
+ ntsync_wa_to_lwa(&lwa, &wa);
+ error1 = copyout(&lwa, data, sizeof(lwa));
+ if (error == 0)
+ error = error1;
+ }
+ }
+ break;
+ case LNTSYNC_IOC_SEM_RELEASE:
+ error = copyin(data, &val, sizeof(val));
+ if (error == 0) {
+ error = ntsync_sem_release(td, fp, &val);
+ if (error == 0)
+ error = copyout(&val, data, sizeof(val));
+ }
+ break;
+ case LNTSYNC_IOC_SEM_READ:
+ error = ntsync_sem_read(td, fp, &sa);
+ if (error == 0) {
+ ntsync_sa_to_lsa(&lsa, &sa);
+ error = copyout(&lsa, data, sizeof(lsa));
+ }
+ break;
+ case LNTSYNC_IOC_MUTEX_UNLOCK:
+ error = copyin(data, &lma, sizeof(lma));
+ ntsync_lma_to_ma(&ma, &lma);
+ if (error == 0) {
+ error = ntsync_mutex_unlock(td, fp, &ma);
+ if (error == 0) {
+ ntsync_ma_to_lma(&lma, &ma);
+ error = copyout(&lma, data, sizeof(lma));
+ }
+ }
+ break;
+ case LNTSYNC_IOC_MUTEX_KILL:
+ error = copyin(data, &val, sizeof(val));
+ if (error == 0)
+ error = ntsync_mutex_kill(td, fp, val);
+ break;
+ case LNTSYNC_IOC_MUTEX_READ:
+ error = ntsync_mutex_read(td, fp, &ma, &doco);
+ if (doco) {
+ ntsync_ma_to_lma(&lma, &ma);
+ error1 = copyout(&lma, data, sizeof(lma));
+ if (error == 0)
+ error = error1;
+ }
+ break;
+ case LNTSYNC_IOC_EVENT_SET:
+ error = ntsync_event_set(td, fp, &val);
+ if (error == 0)
+ error = copyout(&val, data, sizeof(val));
+ break;
+ case LNTSYNC_IOC_EVENT_RESET:
+ error = ntsync_event_reset(td, fp, &val);
+ if (error == 0)
+ error = copyout(&val, data, sizeof(val));
+ break;
+ case LNTSYNC_IOC_EVENT_PULSE:
+ error = ntsync_event_pulse(td, fp, &val);
+ if (error == 0)
+ error = copyout(&val, data, sizeof(val));
+ break;
+ case LNTSYNC_IOC_EVENT_READ:
+ error = ntsync_event_read(td, fp, &ea);
+ if (error == 0) {
+ ntsync_ea_to_lea(&lea, &ea);
+ error = copyout(&lea, data, sizeof(lea));
+ }
+ break;
+ default:
+ error = ENOTTY;
+ break;
+ }
+ fdrop(fp, td);
+out:
+ return (error);
+}
diff --git a/sys/dev/ntsync/linux_ntsync.h b/sys/dev/ntsync/linux_ntsync.h
new file mode 100644
index 000000000000..412eca00bb1e
--- /dev/null
+++ b/sys/dev/ntsync/linux_ntsync.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Kernel support for NT synchronization primitive emulation
+ *
+ * Copyright (C) 2021-2022 Elizabeth Figura <zfigura@codeweavers.com>
+ */
+
+#ifndef __LINUX_NTSYNC_H
+#define __LINUX_NTSYNC_H
+
+#include <sys/types.h>
+
+typedef uint32_t __u32;
+typedef uint64_t __u64;
+
+struct linux_ntsync_sem_args {
+ __u32 count;
+ __u32 max;
+};
+
+struct linux_ntsync_mutex_args {
+ __u32 owner;
+ __u32 count;
+};
+
+struct linux_ntsync_event_args {
+ __u32 manual;
+ __u32 signaled;
+};
+
+#define LINUX_NTSYNC_WAIT_REALTIME 0x1
+
+struct linux_ntsync_wait_args {
+ __u64 timeout;
+ __u64 objs;
+ __u32 count;
+ __u32 index;
+ __u32 flags;
+ __u32 owner;
+ __u32 alert;
+ __u32 pad;
+};
+
+#define LNTSYNC_IOC_CREATE_SEM 0x40084e80
+#define LNTSYNC_IOC_WAIT_ANY 0xc0284e82
+#define LNTSYNC_IOC_WAIT_ALL 0xc0284e83
+#define LNTSYNC_IOC_CREATE_MUTEX 0x40084e84
+#define LNTSYNC_IOC_CREATE_EVENT 0x40084e87
+#define LNTSYNC_IOC_SEM_RELEASE 0xc0044e81
+#define LNTSYNC_IOC_MUTEX_UNLOCK 0xc0084e85
+#define LNTSYNC_IOC_MUTEX_KILL 0x40044e86
+#define LNTSYNC_IOC_EVENT_SET 0x80044e88
+#define LNTSYNC_IOC_EVENT_RESET 0x80044e89
+#define LNTSYNC_IOC_EVENT_PULSE 0x80044e8a
+#define LNTSYNC_IOC_SEM_READ 0x80084e8b
+#define LNTSYNC_IOC_MUTEX_READ 0x80084e8c
+#define LNTSYNC_IOC_EVENT_READ 0x80084e8d
+
+#define LNTSYNC_IOCTL_MIN 0x4e80
+#define LNTSYNC_IOCTL_MAX 0x4eff
+
+#endif
diff --git a/sys/dev/ntsync/ntsync.c b/sys/dev/ntsync/ntsync.c
new file mode 100644
index 000000000000..a7b002de7cb6
--- /dev/null
+++ b/sys/dev/ntsync/ntsync.c
@@ -0,0 +1,1420 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2026 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ */
+
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/file.h>
+#include <sys/filedesc.h>
+#include <sys/kernel.h>
+#include <sys/limits.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/proc.h>
+#include <sys/stat.h>
+#include <sys/sysent.h>
+#include <sys/user.h>
+#include <dev/ntsync/ntsyncvar.h>
+
+static struct cdev *ntsync_cdev;
+MALLOC_DEFINE(M_NTSYNC, "ntsync", "ntsync");
+
+static void ntsync_free_priv(struct ntsync_priv *priv);
+
+/*
+ * Returning error from an ioctl handler prevents the generic ioctl
+ * code from copying out the result. Use direct access to ioctl(2)
+ * args to get the parameters block pointer to implement Linux
+ * semantic of both returning an error and updating the parameters
+ * block.
+ */
+static int
+ntsync_ioctl_copyout(struct thread *td, const void *ptr, size_t sz)
+{
+ void *uptr;
+
+ if (SV_PROC_ABI(td->td_proc) != SV_ABI_FREEBSD)
+ return (0);
+ uptr = (void *)(uintptr_t)td->td_sa.args[2];
+ return (copyout(ptr, uptr, sz));
+}
+
+static bool
+ntsync_wait_any(struct ntsync_wait_state *state)
+{
+ struct ntsync_obj *obj;
+ int i;
+
+ MPASS(state->any);
+ NTSYNC_PRIV_ASSERT(state->owner);
+
+ for (i = 0; i < state->obj_count; i++) {
+ obj = state->objs[i];
+ if (obj->is_signaled(obj, state, i)) {
+ state->index = i;
+ obj->consume(obj, state, state->index);
+ return (true);
+ }
+ }
+ return (false);
+}
+
+static bool
+ntsync_wait_all_prepare(struct ntsync_wait_state *state, bool *stop)
+{
+ struct ntsync_obj *obj;
+ int alerti, i;
+ bool first;
+
+ MPASS(state->all);
+ MPASS(state->error == 0);
+ MPASS(!*stop);
+ NTSYNC_PRIV_ASSERT(state->owner);
+
+ alerti = state->alert_event == NULL ? 0 : 1;
+ first = true;
+
+ for (i = 0; i < state->obj_count - alerti; i++) {
+ obj = state->objs[i];
+ if (!obj->prepare(obj, state, i, stop))
+ return (false);
+ if (*stop) {
+ MPASS(state->error != 0);
+ return (false);
+ }
+ MPASS (state->error == 0);
+ if (first) {
+ first = false;
+ state->index = i;
+ }
+ }
+ return (true);
+}
+
+static void
+ntsync_wait_all_commit(struct ntsync_wait_state *state)
+{
+ struct ntsync_obj *obj;
+ int i, alerti;
+
+ MPASS(state->all);
+ NTSYNC_PRIV_ASSERT(state->owner);
+ alerti = state->alert_event == NULL ? 0 : 1;
+
+ for (i = 0; i < state->obj_count - alerti; i++) {
+ obj = state->objs[i];
+ obj->commit(obj, state, i);
+ }
+}
+
+static void
+ntsync_wait_link_waiters(struct ntsync_wait_state *state)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_waiter *waiter;
+ int i;
+
+ NTSYNC_PRIV_ASSERT(state->owner);
+
+ for (i = 0; i < state->obj_count; i++) {
+ obj = state->objs[i];
+ waiter = &state->waiters[i];
+ waiter->state = state;
+ TAILQ_INSERT_TAIL(&obj->waiters, waiter, link);
+ }
+}
+
+static void
+ntsync_wait_unlink_waiters(struct ntsync_wait_state *state)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_waiter *waiter;
+ int i;
+
+ NTSYNC_PRIV_ASSERT(state->owner);
+
+ for (i = 0; i < state->obj_count; i++) {
+ obj = state->objs[i];
+ waiter = &state->waiters[i];
+ TAILQ_REMOVE(&obj->waiters, waiter, link);
+ }
+}
+
+static void
+ntsync_wait_post_commit(struct ntsync_wait_state *state)
+{
+ struct ntsync_obj *obj;
+ int alerti, i;
+
+ NTSYNC_PRIV_ASSERT(state->owner);
+
+ alerti = state->alert_event == NULL ? 0 : 1;
+ for (i = 0; i < state->obj_count - alerti; i++) {
+ obj = state->objs[i];
+ obj->post_commit(obj, state, i);
+ }
+}
+
+static void
+ntsync_wait_check_ready(struct ntsync_wait_state *state)
+{
+ struct ntsync_obj *ae;
+ int index;
+ bool stop;
+
+ NTSYNC_PRIV_ASSERT(state->owner);
+
+ if (state->ready)
+ return;
+
+ if (state->all) {
+ stop = false;
+ if (ntsync_wait_all_prepare(state, &stop)) {
+ MPASS(!stop);
+ ntsync_wait_all_commit(state);
+ state->ready = true;
+ ntsync_wait_post_commit(state);
+ } else if (stop) {
+ /* skip */
+ } else if (state->alert_event != NULL) {
+ ae = &state->alert_event->obj;
+ index = state->obj_count - 1;
+ if (ae->is_signaled(ae, state, index)) {
+ state->index = index;
+ ae->consume(ae, state, index);
+ ae->post_commit(ae, state, index);
+ state->ready = true;
+ }
+ }
+ } else { /* state->any */
+ if (ntsync_wait_any(state))
+ state->ready = true;
+ }
+}
+
+/*
+ * Perform the wait. Errors returned through state->error still
+ * result in the copyout of the ntsync_wait_args after the wait, while
+ * errors returned as the function result do not.
+ */
+static int
+ntsync_wait_locked(struct ntsync_wait_state *state, struct thread *td)
+{
+ int error;
+
+ NTSYNC_PRIV_ASSERT(state->owner);
+
+ for (;;) {
+ ntsync_wait_check_ready(state);
+ if (state->ready)
+ break;
+ error = msleep_sbt(state, &state->owner->lock,
+ PCATCH, "ntsync", state->sb, 0,
+ C_ABSOLUTE /* | C_HARDCLOCK XXXKIB */);
+
+ /*
+ * Check state->ready before checking error from
+ * msleep(). If there was a wake up that set the
+ * readiness before us receiving a signal or timeout,
+ * the objects states are modified to reflect wakeup.
+ * Due to this, ready should result in normal return.
+ */
+ if (state->ready) {
+ error = 0;
+ break;
+ }
+
+ if (error != 0) {
+ if (error == EAGAIN)
+ error = ETIMEDOUT;
+ break;
+ }
+ }
+ return (error);
+}
+
+static int
+ntsync_wait(struct ntsync_wait_state *state, struct thread *td)
+{
+ int error;
+
+ NTSYNC_PRIV_LOCK(state->owner);
+ ntsync_wait_link_waiters(state);
+ error = ntsync_wait_locked(state, td);
+ ntsync_wait_unlink_waiters(state);
+ NTSYNC_PRIV_UNLOCK(state->owner);
+ return (error);
+}
+
+static void
+ntsync_wakeup_waiters(struct ntsync_obj *obj)
+{
+ struct ntsync_obj_waiter *w;
+
+ NTSYNC_PRIV_ASSERT(obj->owner);
+
+ TAILQ_FOREACH(w, &obj->waiters, link) {
+ ntsync_wait_check_ready(w->state);
+ if (w->state->ready)
+ wakeup(w->state);
+ }
+}
+
+static int
+ntsync_create_obj(struct ntsync_obj *obj, struct fileops *fops,
+ struct ntsync_priv *priv, struct thread *td)
+{
+ struct file *fp;
+ int error, fd;
+
+ error = falloc_noinstall(td, &fp);
+ if (error != 0)
+ return (error);
+
+ /*
+ * The priv fd cannot be closed during object creation since
+ * it is fget-ed around ioctl.
+ */
+ obj->owner = priv;
+
+ TAILQ_INIT(&obj->waiters);
+ NTSYNC_PRIV_LOCK(priv);
+ MPASS(!priv->closed);
+ if (priv->objs_cnt == UINT_MAX) {
+ NTSYNC_PRIV_UNLOCK(priv);
+ fdrop(fp, td);
+ return (EMFILE);
+ }
+ priv->objs_cnt++;
+ NTSYNC_PRIV_UNLOCK(priv);
+
+ finit(fp, FREAD | FWRITE, DTYPE_NTSYNC, obj, fops);
+ error = finstall(td, fp, &fd, 0, NULL);
+ if (error != 0) {
+ NTSYNC_PRIV_LOCK(priv);
+ MPASS(priv->objs_cnt > 0);
+ priv->objs_cnt--;
+ NTSYNC_PRIV_UNLOCK(priv);
+ } else {
+ td->td_retval[0] = fd;
+ }
+ fdrop(fp, td);
+ return (error);
+}
+
+static void
+ntsync_close_obj(struct ntsync_obj *obj, struct thread *td)
+{
+ struct ntsync_priv *priv;
+
+ priv = obj->owner;
+ NTSYNC_PRIV_LOCK(priv);
+ MPASS(priv->objs_cnt > 0);
+ MPASS(TAILQ_EMPTY(&obj->waiters));
+ priv->objs_cnt--;
+ NTSYNC_PRIV_UNLOCK(priv);
+ ntsync_free_priv(priv);
+}
+
+static bool
+ntsync_sem_is_signaled(struct ntsync_obj *obj, struct ntsync_wait_state *state,
+ int index)
+{
+ struct ntsync_obj_sem *sem;
+
+ MPASS(obj->type == NTSYNC_OBJ_SEM);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ sem = OBJ_TO_SEM(obj);
+ return (sem->a.count != 0);
+}
+
+static void
+ntsync_sem_consume(struct ntsync_obj *obj, struct ntsync_wait_state *state,
+ int index)
+{
+ struct ntsync_obj_sem *sem;
+
+ MPASS(obj->type == NTSYNC_OBJ_SEM);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ sem = OBJ_TO_SEM(obj);
+ MPASS(sem->a.count != 0);
+ sem->a.count--;
+}
+
+static bool
+ntsync_sem_prepare(struct ntsync_obj *obj, struct ntsync_wait_state *state,
+ int index, bool *stop)
+{
+ struct ntsync_obj_sem *sem;
+
+ MPASS(obj->type == NTSYNC_OBJ_SEM);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ sem = OBJ_TO_SEM(obj);
+ if (sem->a.count == 0)
+ return (false);
+ sem->a1 = sem->a;
+ sem->a1.count--;
+ return (true);
+}
+
+static void
+ntsync_sem_commit(struct ntsync_obj *obj, struct ntsync_wait_state *state,
+ int index)
+{
+ struct ntsync_obj_sem *sem;
+
+ MPASS(obj->type == NTSYNC_OBJ_SEM);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ sem = OBJ_TO_SEM(obj);
+ sem->a = sem->a1;
+}
+
+static void
+ntsync_sem_post_commit(struct ntsync_obj *obj, struct ntsync_wait_state *state,
+ int index)
+{
+}
+
+static int
+ntsync_sem_close(struct file *fp, struct thread *td)
+{
+ struct ntsync_obj_sem *sem;
+
+ sem = fp->f_data;
+ ntsync_close_obj(&sem->obj, td);
+ free(sem, M_NTSYNC);
+ return (0);
+}
+
+int
+ntsync_sem_release(struct thread *td, struct file *fp, uint32_t *val)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_sem *sem;
+ struct ntsync_priv *priv;
+ uint32_t prev;
+ int error;
+
+ obj = fp->f_data;
+ if (obj->type != NTSYNC_OBJ_SEM)
+ return (EINVAL);
+ sem = OBJ_TO_SEM(obj);
+ priv = obj->owner;
+ error = 0;
+
+ NTSYNC_PRIV_LOCK(priv);
+ if (sem->a.count + *val < sem->a.count ||
+ sem->a.count + *val > sem->a.max) {
+ error = EOVERFLOW;
+ } else {
+ prev = sem->a.count;
+ sem->a.count += *val;
+ if (sem->a.count != 0)
+ ntsync_wakeup_waiters(obj);
+ *val = prev;
+ }
+ NTSYNC_PRIV_UNLOCK(priv);
+ return (error);
+}
+
+int
+ntsync_sem_read(struct thread *td, struct file *fp, struct ntsync_sem_args *a)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_sem *sem;
+ struct ntsync_priv *priv;
+
+ obj = fp->f_data;
+ if (obj->type != NTSYNC_OBJ_SEM)
+ return (EINVAL);
+ sem = OBJ_TO_SEM(obj);
+ priv = obj->owner;
+ NTSYNC_PRIV_LOCK(priv);
+ *a = sem->a;
+ NTSYNC_PRIV_UNLOCK(priv);
+ return (0);
+}
+
+static int
+ntsync_sem_ioctl(struct file *fp, u_long com, void *data,
+ struct ucred *active_cred, struct thread *td)
+{
+ int error;
+
+ switch (com) {
+ case NTSYNC_IOC_SEM_RELEASE:
+ error = ntsync_sem_release(td, fp, data);
+ break;
+ case NTSYNC_IOC_SEM_READ:
+ error = ntsync_sem_read(td, fp, data);
+ break;
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return (error);
+}
+
+static int
+ntsync_sem_stat(struct file *fp, struct stat *sbp, struct ucred *cred)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_sem *sem;
+
+ MPASS(fp->f_type == DTYPE_NTSYNC);
+ obj = fp->f_data;
+ MPASS(obj->type == NTSYNC_OBJ_SEM);
+ sem = OBJ_TO_SEM(obj);
+
+ memset(sbp, 0, sizeof(*sbp));
+ sbp->st_mode = S_IFREG /* XXXKIB */ | S_IRUSR | S_IWUSR;
+ NTSYNC_PRIV_LOCK(obj->owner);
+ sbp->st_size = sem->a.max;
+ sbp->st_nlink = sem->a.count;
+ NTSYNC_PRIV_UNLOCK(obj->owner);
+ return (0);
+}
+
+static int
+ntsync_sem_fill_kinfo(struct file *fp, struct kinfo_file *kif,
+ struct filedesc *fdp)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_sem *sem;
+
+ MPASS(fp->f_type == DTYPE_NTSYNC);
+ obj = fp->f_data;
+ MPASS(obj->type == NTSYNC_OBJ_SEM);
+ sem = OBJ_TO_SEM(obj);
+
+ kif->kf_type = KF_TYPE_NTSYNC;
+ kif->kf_un.kf_ntsync.kf_ntsync_type = KF_NTSYNC_TYPE_SEM;
+ kif->kf_un.kf_ntsync.kf_ntsync_dev = (uintptr_t)obj->owner;
+ kif->kf_un.kf_ntsync.kf_ntsync_un.kf_ntsync_sem.count = sem->a.count;
+ kif->kf_un.kf_ntsync.kf_ntsync_un.kf_ntsync_sem.max = sem->a.max;
+ return (0);
+}
+
+struct fileops ntsync_sem_fops = {
+ .fo_read = invfo_rdwr,
+ .fo_write = invfo_rdwr,
+ .fo_truncate = invfo_truncate,
+ .fo_ioctl = ntsync_sem_ioctl,
+ .fo_poll = invfo_poll,
+ .fo_kqfilter = invfo_kqfilter,
+ .fo_stat = ntsync_sem_stat,
+ .fo_close = ntsync_sem_close,
+ .fo_chmod = invfo_chmod,
+ .fo_chown = invfo_chown,
+ .fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = ntsync_sem_fill_kinfo,
+ .fo_flags = DFLAG_PASSABLE,
+};
+
+static int
+ntsync_create_sem(struct ntsync_sem_args *args, struct ntsync_priv *priv,
+ struct thread *td)
+{
+ struct ntsync_obj_sem *sem;
+ int error;
+
+ if (args->count > args->max)
+ return (EINVAL);
+
+ sem = malloc(sizeof(*sem), M_NTSYNC, M_WAITOK | M_ZERO);
+ sem->obj.type = NTSYNC_OBJ_SEM;
+ sem->obj.is_signaled = ntsync_sem_is_signaled;
+ sem->obj.consume = ntsync_sem_consume;
+ sem->obj.prepare = ntsync_sem_prepare;
+ sem->obj.commit = ntsync_sem_commit;
+ sem->obj.post_commit = ntsync_sem_post_commit;
+ sem->a = *args;
+
+ error = ntsync_create_obj(&sem->obj, &ntsync_sem_fops, priv, td);
+ if (error != 0)
+ free(sem, M_NTSYNC);
+
+ return (error);
+}
+
+static bool
+ntsync_mutex_can_lock(struct ntsync_obj_mutex *mutex, uint32_t nwa_owner)
+{
+ return (mutex->a.owner == 0 ||
+ (mutex->a.owner == nwa_owner && mutex->a.count < UINT32_MAX) ||
+ mutex->abandoned);
+}
+
+static bool
+ntsync_mutex_is_signaled(struct ntsync_obj *obj,
+ struct ntsync_wait_state *state, int index)
+{
+ struct ntsync_obj_mutex *mutex;
+
+ MPASS(obj->type == NTSYNC_OBJ_MUTEX);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ mutex = OBJ_TO_MUTEX(obj);
+ return (ntsync_mutex_can_lock(mutex, state->nwa->owner));
+}
+
+static void
+ntsync_mutex_consume(struct ntsync_obj *obj, struct ntsync_wait_state *state,
+ int index)
+{
+ struct ntsync_obj_mutex *mutex;
+
+ MPASS(obj->type == NTSYNC_OBJ_MUTEX);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ mutex = OBJ_TO_MUTEX(obj);
+ MPASS(ntsync_mutex_can_lock(mutex, state->nwa->owner));
+ if (state->nwa->owner == 0) {
+ state->error = EINVAL;
+ return;
+ }
+ if (mutex->a.owner == 0 || mutex->abandoned)
+ mutex->a.count = 1;
+ else
+ mutex->a.count++;
+ mutex->a.owner = state->nwa->owner;
+ if (mutex->abandoned && state->error == 0)
+ state->error = EOWNERDEAD;
+ mutex->abandoned = false;
+}
+
+static bool
+ntsync_mutex_prepare(struct ntsync_obj *obj, struct ntsync_wait_state *state,
+ int index, bool *stop)
+{
+ struct ntsync_obj_mutex *mutex;
+
+ MPASS(obj->type == NTSYNC_OBJ_MUTEX);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ mutex = OBJ_TO_MUTEX(obj);
+ if (!ntsync_mutex_can_lock(mutex, state->nwa->owner))
+ return (false);
+ if (state->nwa->owner == 0) {
+ state->error = EINVAL;
+ *stop = true;
+ return (false);
+ }
+ mutex->a1 = mutex->a;
+ if (mutex->a.owner == 0 || mutex->abandoned)
+ mutex->a1.count = 1;
+ else
+ mutex->a1.count++;
+ mutex->a1.owner = state->nwa->owner;
+ return (true);
+}
+
+static void
+ntsync_mutex_commit(struct ntsync_obj *obj, struct ntsync_wait_state *state,
+ int index)
+{
+ struct ntsync_obj_mutex *mutex;
+
+ MPASS(obj->type == NTSYNC_OBJ_MUTEX);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ mutex = OBJ_TO_MUTEX(obj);
+ mutex->a = mutex->a1;
+ if (mutex->abandoned)
+ state->error = EOWNERDEAD;
+ mutex->abandoned = false;
+}
+
+static void
+ntsync_mutex_post_commit(struct ntsync_obj *obj,
+ struct ntsync_wait_state *state, int index)
+{
+}
+
+static int
+ntsync_mutex_close(struct file *fp, struct thread *td)
+{
+ struct ntsync_obj_mutex *mutex;
+
+ mutex = fp->f_data;
+ ntsync_close_obj(&mutex->obj, td);
+ free(mutex, M_NTSYNC);
+ return (0);
+}
+
+int
+ntsync_mutex_unlock(struct thread *td, struct file *fp,
+ struct ntsync_mutex_args *a)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_mutex *mutex;
+ struct ntsync_priv *priv;
+ uint32_t prev;
+ int error;
+
+ obj = fp->f_data;
+ if (obj->type != NTSYNC_OBJ_MUTEX)
+ return (EINVAL);
+ mutex = OBJ_TO_MUTEX(obj);
+ priv = obj->owner;
+
+ NTSYNC_PRIV_LOCK(priv);
+ if (a->owner == 0) {
+ error = EINVAL;
+ } else if (a->owner != mutex->a.owner) {
+ error = EPERM;
+ } else {
+ error = 0;
+ prev = mutex->a.count;
+ MPASS(mutex->a.count > 0);
+ mutex->a.count--;
+ a->count = prev;
+ if (mutex->a.count == 0) {
+ mutex->a.owner = 0;
+ ntsync_wakeup_waiters(obj);
+ }
+ }
+ NTSYNC_PRIV_UNLOCK(priv);
+ return (error);
+}
+
+int
+ntsync_mutex_kill(struct thread *td, struct file *fp, uint32_t val)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_mutex *mutex;
+ struct ntsync_priv *priv;
+ int error;
+
+ obj = fp->f_data;
+ if (obj->type != NTSYNC_OBJ_MUTEX)
+ return (EINVAL);
+ mutex = OBJ_TO_MUTEX(obj);
+ priv = obj->owner;
+
+ NTSYNC_PRIV_LOCK(priv);
+ if (val == 0) {
+ error = EINVAL;
+ } else if (mutex->a.owner != val) {
+ error = EPERM;
+ } else {
+ error = 0;
+ mutex->a.owner = 0;
+ mutex->a.count = 0;
+ mutex->abandoned = true;
+ ntsync_wakeup_waiters(obj);
+ }
+ NTSYNC_PRIV_UNLOCK(priv);
+ return (error);
+}
+
+int
+ntsync_mutex_read(struct thread *td, struct file *fp,
+ struct ntsync_mutex_args *a, bool *doco)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_mutex *mutex;
+ struct ntsync_priv *priv;
+ int error;
+
+ *doco = false;
+ obj = fp->f_data;
+ if (obj->type != NTSYNC_OBJ_MUTEX)
+ return (EINVAL);
+ mutex = OBJ_TO_MUTEX(obj);
+ priv = obj->owner;
+ error = 0;
+
+ NTSYNC_PRIV_LOCK(priv);
+ *a = mutex->a;
+ if (mutex->abandoned)
+ error = EOWNERDEAD;
+ NTSYNC_PRIV_UNLOCK(priv);
+ *doco = true;
+ return (error);
+}
+
+static int
+ntsync_mutex_ioctl(struct file *fp, u_long com, void *data,
+ struct ucred *active_cred, struct thread *td)
+{
+ struct ntsync_mutex_args aa;
+ int error, error1;
+ bool doco;
+
+ doco = false;
+ switch (com) {
+ case NTSYNC_IOC_MUTEX_UNLOCK:
+ error = ntsync_mutex_unlock(td, fp, data);
+ break;
+ case NTSYNC_IOC_MUTEX_KILL:
+ error = ntsync_mutex_kill(td, fp, *(uint32_t *)data);
+ break;
+ case NTSYNC_IOC_MUTEX_READ:
+ error = ntsync_mutex_read(td, fp, &aa, &doco);
+ if (doco) {
+ error1 = ntsync_ioctl_copyout(td, &aa, sizeof(aa));
+ if (error1 != 0)
+ error = error1;
+ }
+ break;
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return (error);
+}
+
+static int
+ntsync_mutex_stat(struct file *fp, struct stat *sbp, struct ucred *cred)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_mutex *mutex;
+
+ MPASS(fp->f_type == DTYPE_NTSYNC);
+ obj = fp->f_data;
+ MPASS(obj->type == NTSYNC_OBJ_MUTEX);
+ mutex = OBJ_TO_MUTEX(obj);
+
+ memset(sbp, 0, sizeof(*sbp));
+ sbp->st_mode = S_IFREG /* XXXKIB */ | S_IRUSR | S_IWUSR;
+ NTSYNC_PRIV_LOCK(obj->owner);
+ sbp->st_size = mutex->a.owner;
+ sbp->st_nlink = mutex->a.count;
+ NTSYNC_PRIV_UNLOCK(obj->owner);
+ return (0);
+}
+
+static int
+ntsync_mutex_fill_kinfo(struct file *fp, struct kinfo_file *kif,
+ struct filedesc *fdp)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_mutex *mutex;
+
+ MPASS(fp->f_type == DTYPE_NTSYNC);
+ obj = fp->f_data;
+ MPASS(obj->type == NTSYNC_OBJ_MUTEX);
+ mutex = OBJ_TO_MUTEX(obj);
+
+ kif->kf_type = KF_TYPE_NTSYNC;
+ kif->kf_un.kf_ntsync.kf_ntsync_type = KF_NTSYNC_TYPE_MUTEX;
+ kif->kf_un.kf_ntsync.kf_ntsync_dev = (uintptr_t)obj->owner;
+ kif->kf_un.kf_ntsync.kf_ntsync_un.kf_ntsync_mutex.owner =
+ mutex->a.owner;
+ kif->kf_un.kf_ntsync.kf_ntsync_un.kf_ntsync_mutex.count =
+ mutex->a.count;
+ return (0);
+}
+
+struct fileops ntsync_mutex_fops = {
+ .fo_read = invfo_rdwr,
+ .fo_write = invfo_rdwr,
+ .fo_truncate = invfo_truncate,
+ .fo_ioctl = ntsync_mutex_ioctl,
+ .fo_poll = invfo_poll,
+ .fo_kqfilter = invfo_kqfilter,
+ .fo_stat = ntsync_mutex_stat,
+ .fo_close = ntsync_mutex_close,
+ .fo_chmod = invfo_chmod,
+ .fo_chown = invfo_chown,
+ .fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = ntsync_mutex_fill_kinfo,
+ .fo_flags = DFLAG_PASSABLE,
+};
+
+static int
+ntsync_create_mutex(struct ntsync_mutex_args *args, struct ntsync_priv *priv,
+ struct thread *td)
+{
+ struct ntsync_obj_mutex *mutex;
+ int error;
+
+ if ((args->owner != 0 && args->count == 0) ||
+ (args->owner == 0 && args->count != 0))
+ return (EINVAL);
+
+ mutex = malloc(sizeof(*mutex), M_NTSYNC, M_WAITOK | M_ZERO);
+ mutex->obj.type = NTSYNC_OBJ_MUTEX;
+ mutex->obj.is_signaled = ntsync_mutex_is_signaled;
+ mutex->obj.consume = ntsync_mutex_consume;
+ mutex->obj.prepare = ntsync_mutex_prepare;
+ mutex->obj.commit = ntsync_mutex_commit;
+ mutex->obj.post_commit = ntsync_mutex_post_commit;
+ mutex->a = *args;
+ mutex->abandoned = false;
+
+ error = ntsync_create_obj(&mutex->obj, &ntsync_mutex_fops, priv, td);
+ if (error != 0)
+ free(mutex, M_NTSYNC);
+
+ return (error);
+}
+
+static bool
+ntsync_event_is_signaled(struct ntsync_obj *obj,
+ struct ntsync_wait_state *state, int index)
+{
+ struct ntsync_obj_event *event;
+
+ MPASS(obj->type == NTSYNC_OBJ_EVENT);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ event = OBJ_TO_EVENT(obj);
+ return (event->a.signaled != 0);
+}
+
+static void
+ntsync_event_consume(struct ntsync_obj *obj, struct ntsync_wait_state *state,
+ int index)
+{
+ struct ntsync_obj_event *event;
+
+ MPASS(obj->type == NTSYNC_OBJ_EVENT);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ MPASS(ntsync_event_is_signaled(obj, state, index));
+
+ event = OBJ_TO_EVENT(obj);
+ if (event->a.manual == 0)
+ event->a.signaled = 0;
+}
+
+static bool
+ntsync_event_prepare(struct ntsync_obj *obj, struct ntsync_wait_state *state,
+ int index, bool *stop)
+{
+ struct ntsync_obj_event *event;
+
+ MPASS(obj->type == NTSYNC_OBJ_EVENT);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ event = OBJ_TO_EVENT(obj);
+ if (!ntsync_event_is_signaled(obj, state, index))
+ return (false);
+ event->a1 = event->a;
+ return (true);
+}
+
+static void
+ntsync_event_commit(struct ntsync_obj *obj, struct ntsync_wait_state *state,
+ int index)
+{
+ struct ntsync_obj_event *event;
+
+ MPASS(obj->type == NTSYNC_OBJ_EVENT);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ event = OBJ_TO_EVENT(obj);
+ event->a = event->a1;
+ if (event->pulse && event->a.manual == 0) {
+ event->a.signaled = 0;
+ event->pulse = false;
+ }
+}
+
+static void
+ntsync_event_post_commit(struct ntsync_obj *obj,
+ struct ntsync_wait_state *state, int index)
+{
+ struct ntsync_obj_event *event;
+
+ MPASS(obj->type == NTSYNC_OBJ_EVENT);
+ NTSYNC_PRIV_ASSERT(obj->owner);
+ event = OBJ_TO_EVENT(obj);
+ if (event->a.manual == 0)
+ event->a.signaled = 0;
+}
+
+static int
+ntsync_event_close(struct file *fp, struct thread *td)
+{
+ struct ntsync_obj_event *event;
+
+ event = fp->f_data;
+ ntsync_close_obj(&event->obj, td);
+ free(event, M_NTSYNC);
+ return (0);
+}
+
+int
+ntsync_event_set(struct thread *td, struct file *fp, uint32_t *val)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_event *event;
+ struct ntsync_priv *priv;
+ uint32_t prev;
+
+ obj = fp->f_data;
+ if (obj->type != NTSYNC_OBJ_EVENT)
+ return (EINVAL);
+ event = OBJ_TO_EVENT(obj);
+ priv = obj->owner;
+
+ NTSYNC_PRIV_LOCK(priv);
+ prev = event->a.signaled;
+ event->a.signaled = 1;
+ ntsync_wakeup_waiters(obj);
+ NTSYNC_PRIV_UNLOCK(priv);
+
+ *val = prev;
+ return (0);
+}
+
+int
+ntsync_event_reset(struct thread *td, struct file *fp, uint32_t *val)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_event *event;
+ struct ntsync_priv *priv;
+ uint32_t prev;
+
+ obj = fp->f_data;
+ if (obj->type != NTSYNC_OBJ_EVENT)
+ return (EINVAL);
+ event = OBJ_TO_EVENT(obj);
+ priv = obj->owner;
+
+ NTSYNC_PRIV_LOCK(priv);
+ prev = event->a.signaled;
+ event->a.signaled = 0;
+ NTSYNC_PRIV_UNLOCK(priv);
+
+ *val = prev;
+ return (0);
+}
+
+int
+ntsync_event_pulse(struct thread *td, struct file *fp, uint32_t *val)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_event *event;
+ struct ntsync_priv *priv;
+ uint32_t prev;
+
+ obj = fp->f_data;
+ if (obj->type != NTSYNC_OBJ_EVENT)
+ return (EINVAL);
+ event = OBJ_TO_EVENT(obj);
+ priv = obj->owner;
+
+ NTSYNC_PRIV_LOCK(priv);
+ prev = event->a.signaled;
+ event->a.signaled = 1;
+ event->pulse = true;
+ ntsync_wakeup_waiters(obj);
+ event->a.signaled = 0;
+ event->pulse = false;
+ NTSYNC_PRIV_UNLOCK(priv);
+
+ *val = prev;
+ return (0);
+}
+
+int
+ntsync_event_read(struct thread *td, struct file *fp,
+ struct ntsync_event_args *a)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_event *event;
+ struct ntsync_priv *priv;
+
+ obj = fp->f_data;
+ if (obj->type != NTSYNC_OBJ_EVENT)
+ return (EINVAL);
+ event = OBJ_TO_EVENT(obj);
+ priv = obj->owner;
+
+ NTSYNC_PRIV_LOCK(priv);
+ *a = event->a;
+ NTSYNC_PRIV_UNLOCK(priv);
+
+ return (0);
+}
+
+static int
+ntsync_event_ioctl(struct file *fp, u_long com, void *data,
+ struct ucred *active_cred, struct thread *td)
+{
+ int error;
+
+ switch (com) {
+ case NTSYNC_IOC_EVENT_SET:
+ error = ntsync_event_set(td, fp, data);
+ break;
+ case NTSYNC_IOC_EVENT_RESET:
+ error = ntsync_event_reset(td, fp, data);
+ break;
+ case NTSYNC_IOC_EVENT_PULSE:
+ error = ntsync_event_pulse(td, fp, data);
+ break;
+ case NTSYNC_IOC_EVENT_READ:
+ error = ntsync_event_read(td, fp, data);
+ break;
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return (error);
+}
+
+static int
+ntsync_event_stat(struct file *fp, struct stat *sbp, struct ucred *cred)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_event *event;
+
+ MPASS(fp->f_type == DTYPE_NTSYNC);
+ obj = fp->f_data;
+ MPASS(obj->type == NTSYNC_OBJ_EVENT);
+ event = OBJ_TO_EVENT(obj);
+
+ memset(sbp, 0, sizeof(*sbp));
+ sbp->st_mode = S_IFREG /* XXXKIB */ | S_IRUSR | S_IWUSR;
+ NTSYNC_PRIV_LOCK(obj->owner);
+ sbp->st_size = event->a.signaled;
+ sbp->st_nlink = event->a.manual;
+ NTSYNC_PRIV_UNLOCK(obj->owner);
+ return (0);
+}
+
+static int
+ntsync_event_fill_kinfo(struct file *fp, struct kinfo_file *kif,
+ struct filedesc *fdp)
+{
+ struct ntsync_obj *obj;
+ struct ntsync_obj_event *event;
+
+ MPASS(fp->f_type == DTYPE_NTSYNC);
+ obj = fp->f_data;
+ MPASS(obj->type == NTSYNC_OBJ_EVENT);
+ event = OBJ_TO_EVENT(obj);
+
+ kif->kf_type = KF_TYPE_NTSYNC;
+ kif->kf_un.kf_ntsync.kf_ntsync_type = KF_NTSYNC_TYPE_EVENT;
+ kif->kf_un.kf_ntsync.kf_ntsync_dev = (uintptr_t)obj->owner;
+ kif->kf_un.kf_ntsync.kf_ntsync_un.kf_ntsync_event.signaled =
+ event->a.signaled;
+ kif->kf_un.kf_ntsync.kf_ntsync_un.kf_ntsync_event.manual =
+ event->a.manual;
+ return (0);
+}
+
+struct fileops ntsync_event_fops = {
+ .fo_read = invfo_rdwr,
+ .fo_write = invfo_rdwr,
+ .fo_truncate = invfo_truncate,
+ .fo_ioctl = ntsync_event_ioctl,
+ .fo_poll = invfo_poll,
+ .fo_kqfilter = invfo_kqfilter,
+ .fo_stat = ntsync_event_stat,
+ .fo_close = ntsync_event_close,
+ .fo_chmod = invfo_chmod,
+ .fo_chown = invfo_chown,
+ .fo_sendfile = invfo_sendfile,
+ .fo_fill_kinfo = ntsync_event_fill_kinfo,
+ .fo_flags = DFLAG_PASSABLE,
+};
+
+static int
+ntsync_create_event(struct ntsync_event_args *args, struct ntsync_priv *priv,
+ struct thread *td)
+{
+ struct ntsync_obj_event *event;
+ int error;
+
+ event = malloc(sizeof(*event), M_NTSYNC, M_WAITOK | M_ZERO);
+ event->obj.type = NTSYNC_OBJ_EVENT;
+ event->obj.is_signaled = ntsync_event_is_signaled;
+ event->obj.consume = ntsync_event_consume;
+ event->obj.prepare = ntsync_event_prepare;
+ event->obj.commit = ntsync_event_commit;
+ event->obj.post_commit = ntsync_event_post_commit;
+ event->a = *args;
+
+ error = ntsync_create_obj(&event->obj, &ntsync_event_fops, priv, td);
+ if (error != 0)
+ free(event, M_NTSYNC);
+
+ return (error);
+}
+
+static void
+ntsync_free_priv(struct ntsync_priv *priv)
+{
+ bool do_free;
+
+ NTSYNC_PRIV_LOCK(priv);
+ do_free = priv->closed && priv->objs_cnt == 0;
+ NTSYNC_PRIV_UNLOCK(priv);
+ if (do_free) {
+ mtx_destroy(&priv->lock);
+ free(priv, M_NTSYNC);
+ }
+}
+
+static void
+ntsync_priv_dtr(void *data)
+{
+ ntsync_free_priv(data);
+}
+
+static int
+ntsync_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+{
+ struct ntsync_priv *priv;
+
+ priv = malloc(sizeof(*priv), M_NTSYNC, M_WAITOK);
+ priv->closed = false;
+ priv->objs_cnt = 0;
+ mtx_init(&priv->lock, "ntsync", "ntsync", MTX_DEF | MTX_NEW);
+ devfs_set_cdevpriv(priv, ntsync_priv_dtr);
+ return (0);
+}
+
+static int
+ntsync_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
+{
+ struct ntsync_priv *priv;
+ void *a;
+ int error;
+
+ error = devfs_get_cdevpriv(&a);
+ if (error == 0) {
+ priv = a;
+ NTSYNC_PRIV_LOCK(priv);
+ priv->closed = true;
+ NTSYNC_PRIV_UNLOCK(priv);
+ }
+ devfs_clear_cdevpriv();
+ return (0);
+}
+
+static int
+ntsync_wait_state_get(struct ntsync_wait_args *nwa, u_long cmd,
+ struct ntsync_priv *owner, struct ntsync_wait_state **statep,
+ struct thread *td)
+{
+ struct ntsync_wait_state *state;
+ struct ntsync_obj *obj;
+ struct bintime btb;
+ int error, i, j;
+
+ if (nwa->count > NTSYNC_MAX_WAIT_COUNT)
+ return (EINVAL);
+ if ((nwa->flags & ~NTSYNC_WAIT_REALTIME) != 0)
+ return (EINVAL);
+
+ state = malloc(sizeof(*state), M_NTSYNC, M_WAITOK | M_ZERO);
+ state->nwa = nwa;
+ state->owner = owner;
+ state->all = cmd == NTSYNC_IOC_WAIT_ALL;
+ state->any = !state->all;
+ error = copyin((void *)(uintptr_t)nwa->objs, &state->fds[0],
+ nwa->count * sizeof(state->fds[0]));
+ if (error != 0)
+ return (error);
+
+ i = 0;
+ if (nwa->alert != 0) {
+ error = fget_cap(td, nwa->alert, &cap_no_rights, NULL,
+ &state->fp_alert, NULL);
+ if (error != 0) {
+ state->fp_alert = NULL;
+ goto error_out;
+ }
+ if (state->fp_alert->f_type != DTYPE_NTSYNC) {
+ error = EINVAL;
+ goto error_out;
+ }
+ obj = state->fp_alert->f_data;
+ if (obj->type != NTSYNC_OBJ_EVENT || obj->owner != owner) {
+ error = EINVAL;
+ goto error_out;
+ }
+ state->alert_event = OBJ_TO_EVENT(obj);
+ }
+
+ for (; i < nwa->count; i++) {
+ error = fget_cap(td, state->fds[i], &cap_no_rights, NULL,
+ &state->fps[i], NULL);
+ if (error != 0) {
+ state->fps[i] = NULL;
+ goto error_out;
+ }
+ if (state->fps[i]->f_type != DTYPE_NTSYNC ||
+ (obj = state->fps[i]->f_data)->owner != owner) {
+ i++;
+ error = EINVAL;
+ goto error_out;
+ }
+ }
+
+ state->obj_count = nwa->count;
+ for (i = 0; i < nwa->count; i++)
+ state->objs[i] = state->fps[i]->f_data;
+ if (state->alert_event != NULL) {
+ state->objs[i] = &state->alert_event->obj;
+ state->obj_count++;
+ }
+
+ if (state->all) {
+ /* Check no dups */
+ for (i = 0; i < state->obj_count; i++) {
+ obj = state->objs[i];
+ for (j = i + 1; j < state->obj_count; j++) {
+ if (obj == state->objs[j]) {
+ i = state->obj_count;
+ error = EINVAL;
+ goto error_out;
+ }
+ }
+ }
+ }
+
+ if (nwa->timeout == UINT64_MAX) {
+ state->sb = 0;
+ } else {
+ state->sb = nstosbt(nwa->timeout);
+ if ((nwa->flags & NTSYNC_WAIT_REALTIME) != 0) {
+ getboottimebin(&btb);
+ state->sb += bttosbt(btb);
+ }
+ }
+
+ *statep = state;
+ return (0);
+
+error_out:
+ for (j = 0; j < i; j++)
+ fdrop(state->fps[j], td);
+ if (state->fp_alert != NULL)
+ fdrop(state->fp_alert, td);
+ return (error);
+}
+
+static void
+ntsync_wait_state_put(struct ntsync_wait_state *state, struct thread *td)
+{
+ int i;
+
+ for (i = 0; i < state->nwa->count; i++)
+ fdrop(state->fps[i], td);
+ if (state->fp_alert != NULL)
+ fdrop(state->fp_alert, td);
+ free(state, M_NTSYNC);
+}
+
+static int
+ntsync_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
+ struct thread *td)
+{
+ struct ntsync_priv *owner;
+ struct ntsync_wait_args *nwa;
+ struct ntsync_wait_state *state;
+ void *a;
+ int error;
+
+ error = devfs_get_cdevpriv(&a);
+ if (error != 0)
+ return (error);
+ owner = a;
+
+ switch (cmd) {
+ case NTSYNC_IOC_CREATE_SEM:
+ error = ntsync_create_sem((struct ntsync_sem_args *)data,
+ owner, td);
+ break;
+ case NTSYNC_IOC_CREATE_MUTEX:
+ error = ntsync_create_mutex((struct ntsync_mutex_args *)data,
+ owner, td);
+ break;
+ case NTSYNC_IOC_CREATE_EVENT:
+ error = ntsync_create_event((struct ntsync_event_args *)data,
+ owner, td);
+ break;
+ case NTSYNC_IOC_WAIT_ANY:
+ nwa = (struct ntsync_wait_args *)data;
+ error = ntsync_wait_state_get(nwa, cmd, owner, &state, td);
+ if (error != 0)
+ break;
+ error = ntsync_wait(state, td);
+ if (error == 0) {
+ nwa->index = state->index;
+ error = ntsync_ioctl_copyout(td, nwa, sizeof(*nwa));
+ if (error == 0)
+ error = state->error;
+ }
+ ntsync_wait_state_put(state, td);
+ break;
+ case NTSYNC_IOC_WAIT_ALL:
+ nwa = (struct ntsync_wait_args *)data;
+ error = ntsync_wait_state_get(nwa, cmd, owner, &state, td);
+ if (error != 0)
+ break;
+ error = ntsync_wait(state, td);
+ if (error == 0) {
+ nwa->index = state->index;
+ error = ntsync_ioctl_copyout(td, nwa, sizeof(*nwa));
+ if (error == 0)
+ error = state->error;
+ }
+ ntsync_wait_state_put(state, td);
+ break;
+
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return (error);
+}
+
+struct cdevsw ntsync_cdevsw = {
+ .d_version = D_VERSION,
+ .d_flags = 0,
+ .d_open = ntsync_open,
+ .d_close = ntsync_close,
+ .d_ioctl = ntsync_ioctl,
+ .d_name = "ntsync",
+};
+
+static int
+ntsync_modevent(module_t mod __unused, int type, void *data __unused)
+{
+ struct make_dev_args mda;
+ int error;
+
+ error = 0;
+ switch (type) {
+ case MOD_LOAD:
+ make_dev_args_init(&mda);
+ mda.mda_flags = MAKEDEV_WAITOK | MAKEDEV_CHECKNAME;
+ mda.mda_devsw = &ntsync_cdevsw;
+ mda.mda_uid = UID_ROOT;
+ mda.mda_gid = GID_GAMES;
+ mda.mda_mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP |
+ S_IROTH | S_IWOTH;
+
+ error = make_dev_s(&mda, &ntsync_cdev, "ntsync");
+ if (error != 0) {
+ printf("cannot create ntsync dev err %d\n", error);
+ break;
+ }
+ if (bootverbose)
+ printf("ntsync\n");
+ break;
+
+ case MOD_UNLOAD:
+ destroy_dev(ntsync_cdev);
+ break;
+
+ case MOD_SHUTDOWN:
+ break;
+
+ default:
+ error = EOPNOTSUPP;
+ }
+
+ return (error);
+}
+
+DEV_MODULE(ntsync, ntsync_modevent, NULL);
+MODULE_VERSION(ntsync, 1);
diff --git a/sys/dev/ntsync/ntsync.h b/sys/dev/ntsync/ntsync.h
new file mode 100644
index 000000000000..cbfc1cf2dcc4
--- /dev/null
+++ b/sys/dev/ntsync/ntsync.h
@@ -0,0 +1,66 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2026 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ */
+
+#ifndef __DEV_NTSYNC_H__
+#define __DEV_NTSYNC_H__
+
+#include <sys/types.h>
+#include <sys/ioccom.h>
+
+struct ntsync_sem_args {
+ uint32_t count;
+ uint32_t max;
+};
+
+struct ntsync_mutex_args {
+ uint32_t owner;
+ uint32_t count;
+};
+
+struct ntsync_event_args {
+ uint32_t manual;
+ uint32_t signaled;
+};
+
+struct ntsync_wait_args {
+ uint64_t timeout;
+ uint64_t objs;
+ uint32_t count;
+ uint32_t index;
+ uint32_t flags;
+ uint32_t owner;
+ uint32_t alert;
+ uint32_t pad;
+};
+
+#define NTSYNC_WAIT_REALTIME 0x00000001
+
+#define NTSYNC_MAX_WAIT_COUNT 64
+
+/*
+ * 'sp' means that the ioctl is special, it might return both error
+ * and copy out parameters. See ntsync_ioctl_copyout().
+ */
+
+#define NTSYNC_IOC_CREATE_SEM _IOW('n', 1, struct ntsync_sem_args)
+#define NTSYNC_IOC_CREATE_MUTEX _IOW('n', 2, struct ntsync_mutex_args)
+#define NTSYNC_IOC_CREATE_EVENT _IOW('n', 3, struct ntsync_event_args)
+#define NTSYNC_IOC_SEM_RELEASE _IOWR('n', 4, uint32_t)
+#define NTSYNC_IOC_MUTEX_UNLOCK _IOWR('n', 5, struct ntsync_mutex_args)
+#define NTSYNC_IOC_EVENT_SET _IOR('n', 6, uint32_t)
+#define NTSYNC_IOC_EVENT_RESET _IOR('n', 7, uint32_t)
+#define NTSYNC_IOC_EVENT_PULSE _IOR('n', 8, uint32_t)
+#define NTSYNC_IOC_SEM_READ _IOR('n', 9, struct ntsync_sem_args)
+#define NTSYNC_IOC_MUTEX_READ _IO('n', 10) /* sp */
+#define NTSYNC_IOC_EVENT_READ _IOR('n', 11, struct ntsync_event_args)
+#define NTSYNC_IOC_MUTEX_KILL _IOW('n', 12, uint32_t)
+#define NTSYNC_IOC_WAIT_ANY _IOW('n', 13, struct ntsync_wait_args) /* sp */
+#define NTSYNC_IOC_WAIT_ALL _IOW('n', 14, struct ntsync_wait_args) /* sp */
+
+#endif
diff --git a/sys/dev/ntsync/ntsyncvar.h b/sys/dev/ntsync/ntsyncvar.h
new file mode 100644
index 000000000000..fd875588e889
--- /dev/null
+++ b/sys/dev/ntsync/ntsyncvar.h
@@ -0,0 +1,119 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright 2026 The FreeBSD Foundation
+ *
+ * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
+ * under sponsorship from the FreeBSD Foundation.
+ */
+
+#ifndef __DEV_NTSYNCVAR_H__
+#define __DEV_NTSYNCVAR_H__
+
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+#include <dev/ntsync/ntsync.h>
+
+enum ntsync_obj_type {
+ NTSYNC_OBJ_SEM,
+ NTSYNC_OBJ_MUTEX,
+ NTSYNC_OBJ_EVENT,
+};
+
+struct ntsync_wait_state;
+
+struct ntsync_obj_waiter {
+ struct ntsync_wait_state *state;
+ TAILQ_ENTRY(ntsync_obj_waiter) link;
+};
+
+struct ntsync_obj {
+ enum ntsync_obj_type type;
+ struct ntsync_priv *owner;
+ TAILQ_HEAD(, ntsync_obj_waiter) waiters;
+ /* any */
+ bool (*is_signaled)(struct ntsync_obj *,
+ struct ntsync_wait_state *state, int index);
+ void (*consume)(struct ntsync_obj *, struct ntsync_wait_state *,
+ int index);
+ /* all */
+ bool (*prepare)(struct ntsync_obj *, struct ntsync_wait_state *state,
+ int index, bool *stop);
+ void (*commit)(struct ntsync_obj *, struct ntsync_wait_state *state,
+ int index);
+ void (*post_commit)(struct ntsync_obj *,
+ struct ntsync_wait_state *state, int index);
+};
+
+struct ntsync_obj_sem {
+ struct ntsync_obj obj;
+ struct ntsync_sem_args a;
+ struct ntsync_sem_args a1;
+};
+#define OBJ_TO_SEM(obj) __containerof(obj, struct ntsync_obj_sem, obj)
+
+struct ntsync_obj_mutex {
+ struct ntsync_obj obj;
+ struct ntsync_mutex_args a;
+ struct ntsync_mutex_args a1;
+ bool abandoned;
+};
+#define OBJ_TO_MUTEX(obj) __containerof(obj, struct ntsync_obj_mutex, obj)
+
+struct ntsync_obj_event {
+ struct ntsync_obj obj;
+ struct ntsync_event_args a;
+ struct ntsync_event_args a1;
+ bool pulse;
+};
+#define OBJ_TO_EVENT(obj) __containerof(obj, struct ntsync_obj_event, obj)
+
+struct ntsync_wait_state {
+ struct ntsync_wait_args *nwa;
+ struct ntsync_priv *owner;
+ struct ntsync_obj_waiter waiters[NTSYNC_MAX_WAIT_COUNT + 1];
+ int fds[NTSYNC_MAX_WAIT_COUNT];
+ struct file *fps[NTSYNC_MAX_WAIT_COUNT];
+ struct file *fp_alert;
+ int obj_count;
+ struct ntsync_obj *objs[NTSYNC_MAX_WAIT_COUNT + 1];
+ struct ntsync_obj_event *alert_event;
+ sbintime_t sb;
+ int error;
+ int index;
+ bool any;
+ bool all;
+ bool ready;
+};
+
+struct ntsync_priv {
+ struct mtx lock;
+ unsigned objs_cnt;
+ bool closed;
+};
+
+#define NTSYNC_PRIV_LOCK(priv) mtx_lock(&priv->lock)
+#define NTSYNC_PRIV_UNLOCK(priv) mtx_unlock(&priv->lock)
+#define NTSYNC_PRIV_ASSERT(priv) mtx_assert(&priv->lock, MA_OWNED)
+
+extern struct cdevsw ntsync_cdevsw;
+
+struct file;
+struct thread;
+int ntsync_sem_release(struct thread *td, struct file *fp, uint32_t *val);
+int ntsync_sem_read(struct thread *td, struct file *fp,
+ struct ntsync_sem_args *a);
+int ntsync_mutex_unlock(struct thread *td, struct file *fp,
+ struct ntsync_mutex_args *a);
+int ntsync_mutex_kill(struct thread *td, struct file *fp, uint32_t val);
+int ntsync_mutex_read(struct thread *td, struct file *fp,
+ struct ntsync_mutex_args *a, bool *doco);
+int ntsync_event_set(struct thread *td, struct file *fp, uint32_t *val);
+int ntsync_event_reset(struct thread *td, struct file *fp, uint32_t *val);
+int ntsync_event_pulse(struct thread *td, struct file *fp, uint32_t *val);
+int ntsync_event_read(struct thread *td, struct file *fp,
+ struct ntsync_event_args *a);
+
+#endif
diff --git a/sys/dev/rtwn/usb/rtwn_usb_attach.h b/sys/dev/rtwn/usb/rtwn_usb_attach.h
index cd5485b36678..ca12480c8f19 100644
--- a/sys/dev/rtwn/usb/rtwn_usb_attach.h
+++ b/sys/dev/rtwn/usb/rtwn_usb_attach.h
@@ -117,6 +117,7 @@ static const STRUCT_USB_HOST_ID rtwn_devs[] = {
{ USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, RTWN_CHIP_RTL8188EU) }
RTWN_RTL8188EU_DEV(ABOCOM, RTL8188EU),
RTWN_RTL8188EU_DEV(ASUS, USBN10NANOB1),
+ RTWN_RTL8188EU_DEV(DLINK, DWA121B1),
RTWN_RTL8188EU_DEV(DLINK, DWA123D1),
RTWN_RTL8188EU_DEV(DLINK, DWA125D1),
RTWN_RTL8188EU_DEV(EDIMAX, EW7811UN_V2),
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
index d98952d7a984..235142eb5209 100644
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -77,11 +77,30 @@ snd_setup_intr(device_t dev, struct resource *res, int flags, driver_intr_t hand
return bus_setup_intr(dev, res, flags, NULL, hand, param, cookiep);
}
+static void
+pcm_hotswap(void)
+{
+ struct snddev_info *d;
+ char buf[32];
+
+ bus_topo_assert();
+ if (snd_unit >= 0) {
+ d = devclass_get_softc(pcm_devclass, snd_unit);
+ if (!PCM_REGISTERED(d))
+ return;
+ snprintf(buf, sizeof(buf), "cdev=dsp%d", snd_unit);
+ if (d->reccount > 0)
+ devctl_notify("SND", "CONN", "IN", buf);
+ if (d->playcount > 0)
+ devctl_notify("SND", "CONN", "OUT", buf);
+ } else
+ devctl_notify("SND", "CONN", "NODEV", NULL);
+}
+
static int
sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS)
{
struct snddev_info *d;
- char buf[32];
int error, unit;
unit = snd_unit;
@@ -95,13 +114,8 @@ sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS)
}
snd_unit = unit;
snd_unit_auto = 0;
+ pcm_hotswap();
bus_topo_unlock();
-
- snprintf(buf, sizeof(buf), "cdev=dsp%d", snd_unit);
- if (d->reccount > 0)
- devctl_notify("SND", "CONN", "IN", buf);
- if (d->playcount > 0)
- devctl_notify("SND", "CONN", "OUT", buf);
}
return (error);
}
@@ -373,6 +387,7 @@ int
pcm_register(device_t dev, char *str)
{
struct snddev_info *d = device_get_softc(dev);
+ int err;
/* should only be called once */
if (d->flags & SD_F_REGISTERED)
@@ -417,6 +432,13 @@ pcm_register(device_t dev, char *str)
vchan_initsys(dev);
feeder_eq_initsys(dev);
+ sndstat_register(dev, SNDST_TYPE_PCM, d->status);
+
+ err = dsp_make_dev(dev);
+ if (err)
+ return (err);
+
+ bus_topo_lock();
if (snd_unit_auto < 0)
snd_unit_auto = (snd_unit < 0) ? 1 : 0;
if (snd_unit < 0 || snd_unit_auto > 1)
@@ -424,9 +446,11 @@ pcm_register(device_t dev, char *str)
else if (snd_unit_auto == 1)
snd_unit = pcm_best_unit(snd_unit);
- sndstat_register(dev, SNDST_TYPE_PCM, d->status);
+ if (snd_unit == device_get_unit(dev))
+ pcm_hotswap();
+ bus_topo_unlock();
- return (dsp_make_dev(dev));
+ return (0);
}
int
@@ -469,13 +493,14 @@ pcm_unregister(device_t dev)
cv_destroy(&d->cv);
mtx_destroy(&d->lock);
+ bus_topo_lock();
if (snd_unit == device_get_unit(dev)) {
snd_unit = pcm_best_unit(-1);
if (snd_unit_auto == 0)
snd_unit_auto = 1;
- if (snd_unit < 0)
- devctl_notify("SND", "CONN", "NODEV", NULL);
+ pcm_hotswap();
}
+ bus_topo_unlock();
return (0);
}
diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c
index 104e51c082c3..d012af99fee4 100644
--- a/sys/dev/usb/input/ukbd.c
+++ b/sys/dev/usb/input/ukbd.c
@@ -957,13 +957,6 @@ ukbd_set_leds_callback(struct usb_xfer *xfer, usb_error_t error)
break;
sc->sc_flags &= ~UKBD_FLAG_SET_LEDS;
- req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
- req.bRequest = UR_SET_REPORT;
- USETW2(req.wValue, UHID_OUTPUT_REPORT, 0);
- req.wIndex[0] = sc->sc_iface_no;
- req.wIndex[1] = 0;
- req.wLength[1] = 0;
-
memset(sc->sc_buffer, 0, UKBD_BUFFER_SIZE);
id = 0;
@@ -1017,11 +1010,18 @@ ukbd_set_leds_callback(struct usb_xfer *xfer, usb_error_t error)
} else {
usbd_copy_in(pc, 0, sc->sc_buffer + 1, len);
}
- req.wLength[0] = len;
usbd_xfer_set_frame_len(xfer, 1, len);
DPRINTF("len=%d, id=%d\n", len, id);
+ req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
+ req.bRequest = UR_SET_REPORT;
+ USETW2(req.wValue, UHID_OUTPUT_REPORT, id);
+ req.wIndex[0] = sc->sc_iface_no;
+ req.wIndex[1] = 0;
+ req.wLength[0] = len;
+ req.wLength[1] = 0;
+
/* setup control request last */
pc = usbd_xfer_get_frame(xfer, 0);
usbd_copy_in(pc, 0, &req, sizeof(req));
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c
index 67745cf49397..d41121ed3a06 100644
--- a/sys/dev/usb/usb_transfer.c
+++ b/sys/dev/usb/usb_transfer.c
@@ -1889,8 +1889,10 @@ usbd_transfer_submit(struct usb_xfer *xfer)
*/
#if USB_HAVE_BUSDMA
if (xfer->flags_int.bdma_enable) {
+ USB_BUS_LOCK(bus);
/* insert the USB transfer last in the BUS-DMA queue */
usb_command_wrapper(&xfer->xroot->dma_q, xfer);
+ USB_BUS_UNLOCK(bus);
return;
}
#endif
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index a6a240d62186..7a9c7431f53d 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -1792,6 +1792,7 @@ product DLINK DWA182C1 0x3315 DWA-182 rev C1
product DLINK DWA180A1 0x3316 DWA-180 rev A1
product DLINK DWA172A1 0x3318 DWA-172 rev A1
product DLINK DWA131E1 0x3319 DWA-131 rev E1
+product DLINK DWA121B1 0x331b DWA-121 rev B1
product DLINK DWA182D1 0x331c DWA-182 rev D1
product DLINK DWA181A1 0x331e DWA-181 rev A1
product DLINK DWL122 0x3700 DWL-122