diff options
Diffstat (limited to 'sys/dev')
595 files changed, 19361 insertions, 10936 deletions
diff --git a/sys/dev/aacraid/aacraid_cam.c b/sys/dev/aacraid/aacraid_cam.c index 919bf1ad55ca..6cb515462f08 100644 --- a/sys/dev/aacraid/aacraid_cam.c +++ b/sys/dev/aacraid/aacraid_cam.c @@ -122,7 +122,7 @@ static device_method_t aacraid_pass_methods[] = { DEVMETHOD(device_probe, aac_cam_probe), DEVMETHOD(device_attach, aac_cam_attach), DEVMETHOD(device_detach, aac_cam_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t aacraid_pass_driver = { diff --git a/sys/dev/aacraid/aacraid_pci.c b/sys/dev/aacraid/aacraid_pci.c index cb4c6fb8eeba..37bcede44878 100644 --- a/sys/dev/aacraid/aacraid_pci.c +++ b/sys/dev/aacraid/aacraid_pci.c @@ -72,7 +72,7 @@ static device_method_t aacraid_methods[] = { DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_driver_added, bus_generic_driver_added), - { 0, 0 } + DEVMETHOD_END }; static driver_t aacraid_pci_driver = { diff --git a/sys/dev/acpi_support/acpi_asus.c b/sys/dev/acpi_support/acpi_asus.c index b9ba6650d2b7..975d7f93554a 100644 --- a/sys/dev/acpi_support/acpi_asus.c +++ b/sys/dev/acpi_support/acpi_asus.c @@ -517,7 +517,7 @@ static device_method_t acpi_asus_methods[] = { DEVMETHOD(device_probe, acpi_asus_probe), DEVMETHOD(device_attach, acpi_asus_attach), DEVMETHOD(device_detach, acpi_asus_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t acpi_asus_driver = { diff --git a/sys/dev/acpi_support/acpi_ibm.c b/sys/dev/acpi_support/acpi_ibm.c index c1302508b8a2..1221384e7d8a 100644 --- a/sys/dev/acpi_support/acpi_ibm.c +++ b/sys/dev/acpi_support/acpi_ibm.c @@ -568,14 +568,14 @@ acpi_ibm_attach(device_t dev) SYSCTL_ADD_PROC(sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, acpi_ibm_sysctls[i].name, - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, + CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, i, acpi_ibm_sysctl, "I", acpi_ibm_sysctls[i].description); } else { SYSCTL_ADD_PROC(sc->sysctl_ctx, SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, acpi_ibm_sysctls[i].name, - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, + CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE, sc, i, acpi_ibm_sysctl, "I", acpi_ibm_sysctls[i].description); } @@ -1447,8 +1447,13 @@ acpi_ibm_eventhandler(struct acpi_ibm_softc *sc, int arg) ACPI_SERIAL_BEGIN(ibm); switch (arg) { + /* + * XXX "Suspend-to-RAM" here is as opposed to suspend-to-disk, but it is + * fine if our suspend sleep state transition request puts us in s2idle + * instead of suspend-to-RAM. + */ case IBM_EVENT_SUSPEND_TO_RAM: - power_pm_suspend(POWER_SLEEP_STATE_SUSPEND); + power_pm_suspend(POWER_SSTATE_TRANSITION_SUSPEND); break; case IBM_EVENT_BLUETOOTH: diff --git a/sys/dev/acpi_support/acpi_panasonic.c b/sys/dev/acpi_support/acpi_panasonic.c index 67d51ea9bc1f..8fea47ee45e8 100644 --- a/sys/dev/acpi_support/acpi_panasonic.c +++ b/sys/dev/acpi_support/acpi_panasonic.c @@ -80,6 +80,8 @@ static int acpi_panasonic_probe(device_t dev); static int acpi_panasonic_attach(device_t dev); static int acpi_panasonic_detach(device_t dev); static int acpi_panasonic_shutdown(device_t dev); +static int acpi_panasonic_resume(device_t dev); +static void acpi_panasonic_clear_rfkill(device_t dev); static int acpi_panasonic_sysctl(SYSCTL_HANDLER_ARGS); static UINT64 acpi_panasonic_sinf(ACPI_HANDLE h, UINT64 index); static void acpi_panasonic_sset(ACPI_HANDLE h, UINT64 index, @@ -116,6 +118,7 @@ static device_method_t acpi_panasonic_methods[] = { DEVMETHOD(device_attach, acpi_panasonic_attach), DEVMETHOD(device_detach, acpi_panasonic_detach), DEVMETHOD(device_shutdown, acpi_panasonic_shutdown), + DEVMETHOD(device_resume, acpi_panasonic_resume), DEVMETHOD_END }; @@ -172,6 +175,8 @@ acpi_panasonic_attach(device_t dev) CTLFLAG_MPSAFE, sc, i, acpi_panasonic_sysctl, "I", ""); } + acpi_panasonic_clear_rfkill(dev); + #if 0 /* Activate hotkeys */ status = AcpiEvaluateObject(sc->handle, "", NULL, NULL); @@ -233,6 +238,37 @@ acpi_panasonic_shutdown(device_t dev) } static int +acpi_panasonic_resume(device_t dev) +{ + + acpi_panasonic_clear_rfkill(dev); + return (0); +} + +static void +acpi_panasonic_clear_rfkill(device_t dev) +{ + ACPI_HANDLE wlsw_handle; + ACPI_STATUS status; + + /* + * Call WLSW.SHRF to clear wireless RF_KILL on models that have it. + * On FZ-Y1 and similar models, the EC latches RF_KILL on shutdown + * and suspend, causing the wireless card to boot with hard block + * enabled. The SHRF method sets the EC state to deassert RF_KILL + * GPIO on mini-PCIe pin 20 via SMI (ASRV call with function + * 0x0F/0x03). + */ + status = AcpiGetHandle(NULL, "\\_SB.WLSW", &wlsw_handle); + if (ACPI_SUCCESS(status)) { + status = AcpiEvaluateObject(wlsw_handle, "SHRF", NULL, NULL); + if (ACPI_FAILURE(status) && bootverbose) + device_printf(dev, "WLSW.SHRF failed: %s\n", + AcpiFormatException(status)); + } +} + +static int acpi_panasonic_sysctl(SYSCTL_HANDLER_ARGS) { struct acpi_panasonic_softc *sc; diff --git a/sys/dev/acpi_support/acpi_system76.c b/sys/dev/acpi_support/acpi_system76.c new file mode 100644 index 000000000000..1ba287ccb85d --- /dev/null +++ b/sys/dev/acpi_support/acpi_system76.c @@ -0,0 +1,592 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Pouria Mousavizadeh Tehrani <pouria@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "opt_acpi.h" + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/sysctl.h> + +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> + +#include <dev/acpica/acpivar.h> +#include <dev/backlight/backlight.h> + +#include "backlight_if.h" + +#define _COMPONENT ACPI_OEM +ACPI_MODULE_NAME("system76") + +static char *system76_ids[] = { "17761776", NULL }; +ACPI_SERIAL_DECL(system76, "System76 ACPI management"); + +struct acpi_ctrl { + int val; + bool exists; +}; + +struct acpi_system76_softc { + device_t dev; + ACPI_HANDLE handle; + + struct acpi_ctrl kbb, /* S76_CTRL_KBB */ + kbc, /* S76_CTRL_KBC */ + bctl, /* S76_CTRL_BCTL */ + bcth; /* S76_CTRL_BCTH */ + + struct sysctl_ctx_list sysctl_ctx; + struct sysctl_oid *sysctl_tree; + struct cdev *kbb_bkl; + uint8_t backlight_level; +}; + +static int acpi_system76_probe(device_t); +static int acpi_system76_attach(device_t); +static int acpi_system76_detach(device_t); +static int acpi_system76_suspend(device_t); +static int acpi_system76_resume(device_t); +static int acpi_system76_shutdown(device_t); +static void acpi_system76_init(struct acpi_system76_softc *); +static struct acpi_ctrl * + acpi_system76_ctrl_map(struct acpi_system76_softc *, int); +static int acpi_system76_update(struct acpi_system76_softc *, int, bool); +static int acpi_system76_sysctl_handler(SYSCTL_HANDLER_ARGS); +static void acpi_system76_notify_handler(ACPI_HANDLE, uint32_t, void *); +static void acpi_system76_check(struct acpi_system76_softc *); +static int acpi_system76_backlight_update_status(device_t dev, + struct backlight_props *props); +static int acpi_system76_backlight_get_status(device_t dev, + struct backlight_props *props); +static int acpi_system76_backlight_get_info(device_t dev, + struct backlight_info *info); + +/* methods */ +enum { + S76_CTRL_KBB = 1, /* Keyboard Brightness */ + S76_CTRL_KBC = 2, /* Keyboard Color */ + S76_CTRL_BCTL = 3, /* Battery Charging Start Thresholds */ + S76_CTRL_BCTH = 4, /* Battery Charging End Thresholds */ +}; +#define S76_CTRL_MAX 5 + +struct s76_ctrl_table { + char *name; + char *get_method; +#define S76_CTRL_GKBB "\\_SB.S76D.GKBB" +#define S76_CTRL_GKBC "\\_SB.S76D.GKBC" +#define S76_CTRL_GBCT "\\_SB.PCI0.LPCB.EC0.GBCT" + + char *set_method; +#define S76_CTRL_SKBB "\\_SB.S76D.SKBB" +#define S76_CTRL_SKBC "\\_SB.S76D.SKBC" +#define S76_CTRL_SBCT "\\_SB.PCI0.LPCB.EC0.SBCT" + + char *desc; +}; + +static const struct s76_ctrl_table s76_sysctl_table[] = { + [S76_CTRL_KBB] = { + .name = "keyboard_backlight", + .get_method = S76_CTRL_GKBB, + .set_method = S76_CTRL_SKBB, + .desc = "Keyboard Backlight", + }, + [S76_CTRL_KBC] = { + .name = "keyboard_color", + .get_method = S76_CTRL_GKBC, + .set_method = S76_CTRL_SKBC, + .desc = "Keyboard Color", + }, + [S76_CTRL_BCTL] = { + .name = "battery_charge_min", + .get_method = S76_CTRL_GBCT, + .set_method = S76_CTRL_SBCT, + .desc = "Start charging the battery when this threshold is reached (percentage)", + }, + [S76_CTRL_BCTH] = { + .name = "battery_charge_max", + .get_method = S76_CTRL_GBCT, + .set_method = S76_CTRL_SBCT, + .desc = "Stop charging the battery when this threshold is reached (percentage)", + }, +}; + +static device_method_t acpi_system76_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, acpi_system76_probe), + DEVMETHOD(device_attach, acpi_system76_attach), + DEVMETHOD(device_detach, acpi_system76_detach), + DEVMETHOD(device_suspend, acpi_system76_suspend), + DEVMETHOD(device_resume, acpi_system76_resume), + DEVMETHOD(device_shutdown, acpi_system76_shutdown), + + /* Backlight interface */ + DEVMETHOD(backlight_update_status, acpi_system76_backlight_update_status), + DEVMETHOD(backlight_get_status, acpi_system76_backlight_get_status), + DEVMETHOD(backlight_get_info, acpi_system76_backlight_get_info), + + DEVMETHOD_END +}; + +/* Notify event */ +#define ACPI_NOTIFY_BACKLIGHT_CHANGED 0x80 +#define ACPI_NOTIFY_COLOR_TOGGLE 0x81 +#define ACPI_NOTIFY_COLOR_DOWN 0x82 +#define ACPI_NOTIFY_COLOR_UP 0x83 +#define ACPI_NOTIFY_COLOR_CHANGED 0x84 + +static driver_t acpi_system76_driver = { + "acpi_system76", + acpi_system76_methods, + sizeof(struct acpi_system76_softc) +}; + +static const uint32_t acpi_system76_backlight_levels[] = { + 0, 6, 12, 18, 24, 30, 36, 42, + 48, 54, 60, 66, 72, 78, 84, 100 +}; + +static inline uint32_t +devstate_to_backlight(uint32_t val) +{ + return (acpi_system76_backlight_levels[val >> 4 & 0xf]); +} + +static inline uint32_t +backlight_to_devstate(uint32_t bkl) +{ + int i; + uint32_t val; + + for (i = 0; i < nitems(acpi_system76_backlight_levels); i++) { + if (bkl < acpi_system76_backlight_levels[i]) + break; + } + val = (i - 1) * 16; + if (val > 224) + val = 255; + return (val); +} + +/* + * Returns corresponding acpi_ctrl of softc from method + */ +static struct acpi_ctrl * +acpi_system76_ctrl_map(struct acpi_system76_softc *sc, int method) +{ + + switch (method) { + case S76_CTRL_KBB: + return (&sc->kbb); + case S76_CTRL_KBC: + return (&sc->kbc); + case S76_CTRL_BCTL: + return (&sc->bctl); + case S76_CTRL_BCTH: + return (&sc->bcth); + default: + device_printf(sc->dev, "Driver received unknown method\n"); + return (NULL); + } +} + +static int +acpi_system76_update(struct acpi_system76_softc *sc, int method, bool set) +{ + struct acpi_ctrl *ctrl; + ACPI_STATUS status; + ACPI_BUFFER Buf; + ACPI_OBJECT Arg[2], Obj; + ACPI_OBJECT_LIST Args; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + ACPI_SERIAL_ASSERT(system76); + + if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL) + return (EINVAL); + + switch (method) { + case S76_CTRL_BCTL: + case S76_CTRL_BCTH: + Arg[0].Type = ACPI_TYPE_INTEGER; + Arg[0].Integer.Value = method == S76_CTRL_BCTH ? 1 : 0; + Args.Count = set ? 2 : 1; + Args.Pointer = Arg; + Buf.Length = sizeof(Obj); + Buf.Pointer = &Obj; + + if (set) { + Arg[1].Type = ACPI_TYPE_INTEGER; + Arg[1].Integer.Value = ctrl->val; + + status = AcpiEvaluateObject(sc->handle, + s76_sysctl_table[method].set_method, &Args, &Buf); + } else { + status = AcpiEvaluateObject(sc->handle, + s76_sysctl_table[method].get_method, &Args, &Buf); + if (ACPI_SUCCESS(status) && + Obj.Type == ACPI_TYPE_INTEGER) + ctrl->val = Obj.Integer.Value; + } + break; + case S76_CTRL_KBB: + case S76_CTRL_KBC: + if (set) + status = acpi_SetInteger(sc->handle, s76_sysctl_table[method].set_method, + ctrl->val); + else + status = acpi_GetInteger(sc->handle, s76_sysctl_table[method].get_method, + &ctrl->val); + break; + } + + if (ACPI_FAILURE(status)) { + device_printf(sc->dev, "Couldn't query method (%s)\n", + s76_sysctl_table[method].name); + return (status); + } + + return (0); +} + +static void +acpi_system76_notify_update(void *arg) +{ + struct acpi_system76_softc *sc; + int method; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + sc = (struct acpi_system76_softc *)device_get_softc(arg); + + ACPI_SERIAL_BEGIN(system76); + for (method = 1; method < S76_CTRL_MAX; method++) { + if (method == S76_CTRL_BCTL || + method == S76_CTRL_BCTH) + continue; + acpi_system76_update(sc, method, false); + } + ACPI_SERIAL_END(system76); + + if (sc->kbb_bkl != NULL) + sc->backlight_level = devstate_to_backlight(sc->kbb.val); +} + +static void +acpi_system76_check(struct acpi_system76_softc *sc) +{ + struct acpi_ctrl *ctrl; + int method; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + ACPI_SERIAL_ASSERT(system76); + + for (method = 1; method < S76_CTRL_MAX; method++) { + if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL) + continue; + + /* available in all models */ + if (method == S76_CTRL_BCTL || + method == S76_CTRL_BCTH) { + ctrl->exists = true; + acpi_system76_update(sc, method, false); + continue; + } + + if (ACPI_FAILURE(acpi_GetInteger(sc->handle, + s76_sysctl_table[method].get_method, &ctrl->val))) { + ctrl->exists = false; + device_printf(sc->dev, "Driver can't control %s\n", + s76_sysctl_table[method].desc); + } else { + ctrl->exists = true; + acpi_system76_update(sc, method, false); + } + } +} + +static void +acpi_system76_notify_handler(ACPI_HANDLE handle, uint32_t notify, void *ctx) +{ + + ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, notify); + + switch (notify) { + case ACPI_NOTIFY_BACKLIGHT_CHANGED: + case ACPI_NOTIFY_COLOR_TOGGLE: + case ACPI_NOTIFY_COLOR_DOWN: + case ACPI_NOTIFY_COLOR_UP: + case ACPI_NOTIFY_COLOR_CHANGED: + AcpiOsExecute(OSL_NOTIFY_HANDLER, + acpi_system76_notify_update, ctx); + break; + default: + break; + } +} + +static int +acpi_system76_sysctl_handler(SYSCTL_HANDLER_ARGS) +{ + struct acpi_ctrl *ctrl, *ctrl_cmp; + struct acpi_system76_softc *sc; + int val, method, error; + bool update; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + sc = (struct acpi_system76_softc *)oidp->oid_arg1; + method = oidp->oid_arg2; + if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL) + return (EINVAL); + + val = ctrl->val; + error = sysctl_handle_int(oidp, &val, 0, req); + if (error != 0) { + device_printf(sc->dev, "Driver query failed\n"); + return (error); + } + + if (req->newptr == NULL) { + /* + * ACPI will not notify us if battery thresholds changes + * outside this module. Therefore, always fetch those values. + */ + if (method != S76_CTRL_BCTL && method != S76_CTRL_BCTH) + return (error); + update = false; + } else { + /* Input validation */ + switch (method) { + case S76_CTRL_KBB: + if (val > UINT8_MAX || val < 0) + return (EINVAL); + if (sc->kbb_bkl != NULL) + sc->backlight_level = devstate_to_backlight(val); + break; + case S76_CTRL_KBC: + if (val >= (1 << 24) || val < 0) + return (EINVAL); + break; + case S76_CTRL_BCTL: + if ((ctrl_cmp = acpi_system76_ctrl_map(sc, S76_CTRL_BCTH)) == NULL) + return (EINVAL); + if (val > 100 || val < 0 || val >= ctrl_cmp->val) + return (EINVAL); + break; + case S76_CTRL_BCTH: + if ((ctrl_cmp = acpi_system76_ctrl_map(sc, S76_CTRL_BCTL)) == NULL) + return (EINVAL); + if (val > 100 || val < 0 || val <= ctrl_cmp->val) + return (EINVAL); + break; + } + ctrl->val = val; + update = true; + } + + ACPI_SERIAL_BEGIN(system76); + error = acpi_system76_update(sc, method, update); + ACPI_SERIAL_END(system76); + return (error); +} + +static void +acpi_system76_init(struct acpi_system76_softc *sc) +{ + struct acpi_softc *acpi_sc; + struct acpi_ctrl *ctrl; + uint32_t method; + + ACPI_SERIAL_ASSERT(system76); + + acpi_system76_check(sc); + acpi_sc = acpi_device_get_parent_softc(sc->dev); + sysctl_ctx_init(&sc->sysctl_ctx); + sc->sysctl_tree = SYSCTL_ADD_NODE(&sc->sysctl_ctx, + SYSCTL_CHILDREN(acpi_sc->acpi_sysctl_tree), OID_AUTO, "s76", + CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "system76 control"); + + for (method = 1; method < S76_CTRL_MAX; method++) { + if ((ctrl = acpi_system76_ctrl_map(sc, method)) == NULL) + continue; + + if (!ctrl->exists) + continue; + + if (method == S76_CTRL_KBB) { + sc->kbb_bkl = backlight_register("system76_keyboard", sc->dev); + if (sc->kbb_bkl == NULL) + device_printf(sc->dev, "Can not register backlight\n"); + else + sc->backlight_level = devstate_to_backlight(sc->kbb.val); + } + + SYSCTL_ADD_PROC(&sc->sysctl_ctx, + SYSCTL_CHILDREN(sc->sysctl_tree), OID_AUTO, s76_sysctl_table[method].name, + CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, + sc, method, acpi_system76_sysctl_handler, "IU", s76_sysctl_table[method].desc); + } +} + +static int +acpi_system76_backlight_update_status(device_t dev, struct backlight_props + *props) +{ + struct acpi_system76_softc *sc; + + sc = device_get_softc(dev); + if (sc->kbb.val != backlight_to_devstate(props->brightness)) { + sc->kbb.val = backlight_to_devstate(props->brightness); + acpi_system76_update(sc, S76_CTRL_KBB, true); + } + sc->backlight_level = props->brightness; + + return (0); +} + +static int +acpi_system76_backlight_get_status(device_t dev, struct backlight_props *props) +{ + struct acpi_system76_softc *sc; + + sc = device_get_softc(dev); + props->brightness = sc->backlight_level; + props->nlevels = nitems(acpi_system76_backlight_levels); + memcpy(props->levels, acpi_system76_backlight_levels, + sizeof(acpi_system76_backlight_levels)); + + return (0); +} + +static int +acpi_system76_backlight_get_info(device_t dev, struct backlight_info *info) +{ + info->type = BACKLIGHT_TYPE_KEYBOARD; + strlcpy(info->name, "System76 Keyboard", BACKLIGHTMAXNAMELENGTH); + + return (0); +} + +static int +acpi_system76_attach(device_t dev) +{ + struct acpi_system76_softc *sc; + + ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); + + sc = device_get_softc(dev); + sc->dev = dev; + sc->handle = acpi_get_handle(dev); + + AcpiInstallNotifyHandler(sc->handle, ACPI_DEVICE_NOTIFY, + acpi_system76_notify_handler, dev); + + ACPI_SERIAL_BEGIN(system76); + acpi_system76_init(sc); + ACPI_SERIAL_END(system76); + + return (0); +} + +static int +acpi_system76_detach(device_t dev) +{ + struct acpi_system76_softc *sc; + + sc = device_get_softc(dev); + if (sysctl_ctx_free(&sc->sysctl_ctx) != 0) + return (EBUSY); + + AcpiRemoveNotifyHandler(sc->handle, ACPI_SYSTEM_NOTIFY, + acpi_system76_notify_handler); + + if (sc->kbb_bkl != NULL) + backlight_destroy(sc->kbb_bkl); + + return (0); +} + +static int +acpi_system76_suspend(device_t dev) +{ + struct acpi_system76_softc *sc; + struct acpi_ctrl *ctrl; + + sc = device_get_softc(dev); + if ((ctrl = acpi_system76_ctrl_map(sc, S76_CTRL_KBB)) != NULL) { + ctrl->val = 0; + acpi_system76_update(sc, S76_CTRL_KBB, true); + } + + return (0); +} + +static int +acpi_system76_resume(device_t dev) +{ + struct acpi_system76_softc *sc; + struct acpi_ctrl *ctrl; + + sc = device_get_softc(dev); + if ((ctrl = acpi_system76_ctrl_map(sc, S76_CTRL_KBB)) != NULL) { + ctrl->val = backlight_to_devstate(sc->backlight_level); + acpi_system76_update(sc, S76_CTRL_KBB, true); + } + + return (0); +} + +static int +acpi_system76_shutdown(device_t dev) +{ + return (acpi_system76_detach(dev)); +} + +static int +acpi_system76_probe(device_t dev) +{ + int rv; + + if (acpi_disabled("system76") || device_get_unit(dev) > 1) + return (ENXIO); + rv = ACPI_ID_PROBE(device_get_parent(dev), dev, system76_ids, NULL); + if (rv > 0) { + return (rv); + } + + return (BUS_PROBE_VENDOR); +} + +DRIVER_MODULE(acpi_system76, acpi, acpi_system76_driver, 0, 0); +MODULE_VERSION(acpi_system76, 1); +MODULE_DEPEND(acpi_system76, acpi, 1, 1, 1); +MODULE_DEPEND(acpi_system76, backlight, 1, 1, 1); diff --git a/sys/dev/acpica/Osd/OsdHardware.c b/sys/dev/acpica/Osd/OsdHardware.c index fbaf76d2a91a..4252cbc63222 100644 --- a/sys/dev/acpica/Osd/OsdHardware.c +++ b/sys/dev/acpica/Osd/OsdHardware.c @@ -37,6 +37,8 @@ extern int acpi_susp_bounce; +int (*acpi_prepare_sleep)(uint8_t state, uint32_t a, uint32_t b, bool ext); + ACPI_STATUS AcpiOsEnterSleep(UINT8 SleepState, UINT32 RegaValue, UINT32 RegbValue) { @@ -45,6 +47,17 @@ AcpiOsEnterSleep(UINT8 SleepState, UINT32 RegaValue, UINT32 RegbValue) if (acpi_susp_bounce) return (AE_CTRL_TERMINATE); + if (acpi_prepare_sleep != NULL) + { + int ret = acpi_prepare_sleep(SleepState, RegaValue, RegbValue, + ACPI_REDUCED_HARDWARE ? true : AcpiGbl_ReducedHardware); + + if (ret < 0) + return (AE_ERROR); + if (ret > 0) + return (AE_CTRL_TERMINATE); + } + return (AE_OK); } diff --git a/sys/dev/acpica/Osd/OsdSchedule.c b/sys/dev/acpica/Osd/OsdSchedule.c index 0c5eadb87687..f0464709e8ad 100644 --- a/sys/dev/acpica/Osd/OsdSchedule.c +++ b/sys/dev/acpica/Osd/OsdSchedule.c @@ -35,7 +35,6 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> -#include <sys/cpuset.h> #include <sys/kernel.h> #include <sys/kthread.h> #include <sys/malloc.h> @@ -110,13 +109,10 @@ static void acpi_taskq_init(void *arg) { int i; - /* XXX Currently assuming BSP is CPU0. */ - cpuset_t just_bsp = CPUSET_T_INITIALIZER(0x1); acpi_taskq = taskqueue_create_fast("acpi_task", M_NOWAIT, &taskqueue_thread_enqueue, &acpi_taskq); - taskqueue_start_threads_cpuset(&acpi_taskq, acpi_max_threads, PWAIT, - &just_bsp, "acpi_task"); + taskqueue_start_threads(&acpi_taskq, acpi_max_threads, PWAIT, "acpi_task"); if (acpi_task_count > 0) { if (bootverbose) printf("AcpiOsExecute: enqueue %d pending tasks\n", diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index 8380f701d226..bdc197a4fb59 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -58,6 +58,7 @@ #if defined(__i386__) || defined(__amd64__) #include <machine/clock.h> +#include <machine/intr_machdep.h> #include <machine/pci_cfgreg.h> #include <x86/cputypes.h> #include <x86/x86_var.h> @@ -192,6 +193,7 @@ static void acpi_system_eventhandler_sleep(void *arg, enum power_stype stype); static void acpi_system_eventhandler_wakeup(void *arg, enum power_stype stype); +static int acpi_s4bios_sysctl(SYSCTL_HANDLER_ARGS); static enum power_stype acpi_sstate_to_stype(int sstate); static int acpi_sname_to_sstate(const char *sname); static const char *acpi_sstate_to_sname(int sstate); @@ -292,6 +294,17 @@ static char acpi_remove_interface[256]; TUNABLE_STR("hw.acpi.remove_interface", acpi_remove_interface, sizeof(acpi_remove_interface)); +/* + * Automatically apply the Darwin OSI on Apple Mac hardware to obtain + * access to full ACPI hardware support on supported platforms. + * + * This flag automatically overrides any values set by + * `hw.acpi.acpi_install_interface` and unset by + * `hw.acpi.acpi_remove_interface`. + */ +static int acpi_apple_darwin_osi = 1; +TUNABLE_INT("hw.acpi.apple_darwin_osi", &acpi_apple_darwin_osi); + /* Allow users to dump Debug objects without ACPI debugger. */ static int acpi_debug_objects; TUNABLE_INT("debug.acpi.enable_debug_objects", &acpi_debug_objects); @@ -489,7 +502,6 @@ acpi_attach(device_t dev) ACPI_STATUS status; int error, state; UINT32 flags; - UINT8 TypeA, TypeB; char *env; enum power_stype stype; @@ -587,61 +599,6 @@ acpi_attach(device_t dev) goto out; } - /* - * Setup our sysctl tree. - * - * XXX: This doesn't check to make sure that none of these fail. - */ - sysctl_ctx_init(&sc->acpi_sysctl_ctx); - sc->acpi_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_sysctl_ctx, - SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, device_get_name(dev), - CTLFLAG_RD | CTLFLAG_MPSAFE, 0, ""); - SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "supported_sleep_state", - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, - 0, 0, acpi_supported_sleep_state_sysctl, "A", - "List supported ACPI sleep states."); - SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "power_button_state", - CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, - &sc->acpi_power_button_stype, 0, acpi_stype_sysctl, "A", - "Power button ACPI sleep state."); - SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "sleep_button_state", - CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, - &sc->acpi_sleep_button_stype, 0, acpi_stype_sysctl, "A", - "Sleep button ACPI sleep state."); - SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "lid_switch_state", - CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, - &sc->acpi_lid_switch_stype, 0, acpi_stype_sysctl, "A", - "Lid ACPI sleep state. Set to s2idle or s2mem if you want to suspend " - "your laptop when you close the lid."); - SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "suspend_state", CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, - NULL, 0, acpi_suspend_state_sysctl, "A", - "Current ACPI suspend state. This sysctl is deprecated; you probably " - "want to use kern.power.suspend instead."); - SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "standby_state", - CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, - &sc->acpi_standby_sx, 0, acpi_sleep_state_sysctl, "A", - "ACPI Sx state to use when going standby (usually S1 or S2)."); - SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "sleep_delay", CTLFLAG_RW, &sc->acpi_sleep_delay, 0, - "sleep delay in seconds"); - SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "s4bios", CTLFLAG_RW, &sc->acpi_s4bios, 0, - "Use S4BIOS when hibernating."); - SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "verbose", CTLFLAG_RW, &sc->acpi_verbose, 0, "verbose mode"); - SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "disable_on_reboot", CTLFLAG_RW, - &sc->acpi_do_disable, 0, "Disable ACPI when rebooting/halting system"); - SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "handle_reboot", CTLFLAG_RW, - &sc->acpi_handle_reboot, 0, "Use ACPI Reset Register to reboot"); - #if defined(__amd64__) || defined(__i386__) /* * Enable workaround for incorrect ISA IRQ polarity by default on @@ -649,10 +606,6 @@ acpi_attach(device_t dev) */ if (cpu_vendor_id == CPU_VENDOR_INTEL) acpi_override_isa_irq_polarity = 1; - SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), - OID_AUTO, "override_isa_irq_polarity", CTLFLAG_RDTUN, - &acpi_override_isa_irq_polarity, 0, - "Force active-hi polarity for edge-triggered ISA IRQs"); #endif /* @@ -672,24 +625,30 @@ acpi_attach(device_t dev) if (AcpiGbl_FADT.Flags & ACPI_FADT_RESET_REGISTER) sc->acpi_handle_reboot = 1; -#if !ACPI_REDUCED_HARDWARE - /* Only enable S4BIOS by default if the FACS says it is available. */ + /* + * Mark whether S4BIOS is available according to the FACS, and if it is, + * enable it by default. + */ if (AcpiGbl_FACS != NULL && AcpiGbl_FACS->Flags & ACPI_FACS_S4_BIOS_PRESENT) - sc->acpi_s4bios = 1; -#endif + sc->acpi_s4bios = sc->acpi_s4bios_supported = true; /* - * Probe all supported ACPI sleep states. Awake (S0) is always supported. + * Probe all supported ACPI sleep states. Awake (S0) is always supported, + * and suspend-to-idle is always supported on x86 only (at the moment). */ - acpi_supported_sstates[ACPI_STATE_S0] = TRUE; + acpi_supported_sstates[ACPI_STATE_S0] = true; acpi_supported_stypes[POWER_STYPE_AWAKE] = true; - for (state = ACPI_STATE_S1; state <= ACPI_STATE_S5; state++) - if (ACPI_SUCCESS(AcpiEvaluateObject(ACPI_ROOT_OBJECT, - __DECONST(char *, AcpiGbl_SleepStateNames[state]), NULL, NULL)) && - ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB))) { - acpi_supported_sstates[state] = TRUE; +#if defined(__i386__) || defined(__amd64__) + acpi_supported_stypes[POWER_STYPE_SUSPEND_TO_IDLE] = true; +#endif + for (state = ACPI_STATE_S1; state <= ACPI_STATE_S5; state++) { + UINT8 TypeA, TypeB; + + if (ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB))) { + acpi_supported_sstates[state] = true; acpi_supported_stypes[acpi_sstate_to_stype(state)] = true; } + } /* * Dispatch the default sleep type to devices. The lid switch is set @@ -705,13 +664,24 @@ acpi_attach(device_t dev) else if (acpi_supported_sstates[ACPI_STATE_S2]) sc->acpi_standby_sx = ACPI_STATE_S2; - /* Pick the first valid sleep type for the sleep button default. */ + /* + * Pick the first valid sleep type for the sleep button default. If that + * type was hibernate and we support s2idle, set it to that. The sleep + * button prefers s2mem instead of s2idle at the moment as s2idle may not + * yet work reliably on all machines. In the future, we should set this to + * s2idle when ACPI_FADT_LOW_POWER_S0 is set. + */ sc->acpi_sleep_button_stype = POWER_STYPE_UNKNOWN; for (stype = POWER_STYPE_STANDBY; stype <= POWER_STYPE_HIBERNATE; stype++) if (acpi_supported_stypes[stype]) { sc->acpi_sleep_button_stype = stype; break; } + if (sc->acpi_sleep_button_stype == POWER_STYPE_HIBERNATE || + sc->acpi_sleep_button_stype == POWER_STYPE_UNKNOWN) { + if (acpi_supported_stypes[POWER_STYPE_SUSPEND_TO_IDLE]) + sc->acpi_sleep_button_stype = POWER_STYPE_SUSPEND_TO_IDLE; + } acpi_enable_fixed_events(sc); @@ -745,6 +715,71 @@ acpi_attach(device_t dev) if ((error = acpi_machdep_init(dev))) goto out; + /* + * Setup our sysctl tree. + * + * XXX: This doesn't check to make sure that none of these fail. + */ + sysctl_ctx_init(&sc->acpi_sysctl_ctx); + sc->acpi_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_sysctl_ctx, + SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO, device_get_name(dev), + CTLFLAG_RD | CTLFLAG_MPSAFE, 0, ""); + SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "supported_sleep_state", + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, + 0, 0, acpi_supported_sleep_state_sysctl, "A", + "List supported ACPI sleep states."); + SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "power_button_state", + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, + &sc->acpi_power_button_stype, 0, acpi_stype_sysctl, "A", + "Power button ACPI sleep state."); + SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "sleep_button_state", + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, + &sc->acpi_sleep_button_stype, 0, acpi_stype_sysctl, "A", + "Sleep button ACPI sleep state."); + SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "lid_switch_state", + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, + &sc->acpi_lid_switch_stype, 0, acpi_stype_sysctl, "A", + "Lid ACPI sleep state. Set to s2idle or s2mem if you want to suspend " + "your laptop when you close the lid."); + SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "suspend_state", CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, + NULL, 0, acpi_suspend_state_sysctl, "A", + "Current ACPI suspend state. This sysctl is deprecated; you probably " + "want to use kern.power.suspend instead."); + SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "standby_state", + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, + &sc->acpi_standby_sx, 0, acpi_sleep_state_sysctl, "A", + "ACPI Sx state to use when going standby (usually S1 or S2)."); + SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "sleep_delay", CTLFLAG_RW, &sc->acpi_sleep_delay, 0, + "sleep delay in seconds"); + SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "s4bios", CTLTYPE_U8 | CTLFLAG_RW | CTLFLAG_MPSAFE, + sc, 0, acpi_s4bios_sysctl, "CU", + "On hibernate, have the firmware save/restore the machine state (S4BIOS)."); + SYSCTL_ADD_BOOL(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "s4bios_supported", CTLFLAG_RD, &sc->acpi_s4bios_supported, 0, + "Whether firmware supports saving/restoring the machine state (S4BIOS)."); + SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "verbose", CTLFLAG_RW, &sc->acpi_verbose, 0, "verbose mode"); + SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "disable_on_reboot", CTLFLAG_RW, + &sc->acpi_do_disable, 0, "Disable ACPI when rebooting/halting system"); + SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "handle_reboot", CTLFLAG_RW, + &sc->acpi_handle_reboot, 0, "Use ACPI Reset Register to reboot"); +#if defined(__amd64__) || defined(__i386__) + SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree), + OID_AUTO, "override_isa_irq_polarity", CTLFLAG_RDTUN, + &acpi_override_isa_irq_polarity, 0, + "Force active-hi polarity for edge-triggered ISA IRQs"); +#endif + /* Register ACPI again to pass the correct argument of pm_func. */ power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, sc, acpi_supported_stypes); @@ -1119,6 +1154,9 @@ acpi_child_deleted(device_t dev, device_t child) free(dinfo, M_ACPIDEV); } +_Static_assert(ACPI_IVAR_PRIVATE >= ISA_IVAR_LAST, + "ACPI private IVARs overlap with ISA IVARs"); + /* * Handle per-device ivars */ @@ -2093,44 +2131,64 @@ acpi_bus_get_prop(device_t bus, device_t child, const char *propname, } } +static int +acpi_device_pwr_for_sleep_sxd(device_t dev, ACPI_HANDLE handle, int state, + int *dstate) +{ + ACPI_STATUS status; + char sxd[8]; + + /* Note illegal _S0D is evaluated because some systems expect this. */ + snprintf(sxd, sizeof(sxd), "_S%dD", state); + status = acpi_GetInteger(handle, sxd, dstate); + if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { + device_printf(dev, "failed to get %s on %s: %s\n", sxd, + acpi_name(handle), AcpiFormatException(status)); + return (ENXIO); + } + return (0); +} + +/* + * Get the D-state we need to set the device to for entry into the sleep type + * we are currently entering (sc->acpi_stype is set in acpi_EnterSleepState + * before the ACPI bus gets suspended, and thus before this function is called). + * + * If entering s2idle, we will try to enter whichever D-state we would've been + * transitioning to in S3. If we are entering an ACPI S-state, we evaluate the + * relevant _SxD state instead (ACPI 7.3.16 - 7.3.19). + */ int acpi_device_pwr_for_sleep(device_t bus, device_t dev, int *dstate) { - struct acpi_softc *sc; - ACPI_HANDLE handle; - ACPI_STATUS status; - char sxd[8]; - - handle = acpi_get_handle(dev); + struct acpi_softc *sc = device_get_softc(bus); + ACPI_HANDLE handle = acpi_get_handle(dev); + int state; - /* - * XXX If we find these devices, don't try to power them down. - * The serial and IRDA ports on my T23 hang the system when - * set to D3 and it appears that such legacy devices may - * need special handling in their drivers. - */ - if (dstate == NULL || handle == NULL || - acpi_MatchHid(handle, "PNP0500") || - acpi_MatchHid(handle, "PNP0501") || - acpi_MatchHid(handle, "PNP0502") || - acpi_MatchHid(handle, "PNP0510") || - acpi_MatchHid(handle, "PNP0511")) - return (ENXIO); + if (dstate == NULL) + return (EINVAL); - /* - * Override next state with the value from _SxD, if present. - * Note illegal _S0D is evaluated because some systems expect this. - */ - sc = device_get_softc(bus); - snprintf(sxd, sizeof(sxd), "_S%dD", acpi_stype_to_sstate(sc, sc->acpi_stype)); - status = acpi_GetInteger(handle, sxd, dstate); - if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { - device_printf(dev, "failed to get %s on %s: %s\n", sxd, - acpi_name(handle), AcpiFormatException(status)); - return (ENXIO); - } + /* + * XXX If we find these devices, don't try to power them down. + * The serial and IRDA ports on my T23 hang the system when + * set to D3 and it appears that such legacy devices may + * need special handling in their drivers. + */ + if (handle == NULL || + acpi_MatchHid(handle, "PNP0500") || + acpi_MatchHid(handle, "PNP0501") || + acpi_MatchHid(handle, "PNP0502") || + acpi_MatchHid(handle, "PNP0510") || + acpi_MatchHid(handle, "PNP0511")) + return (ENXIO); - return (0); + if (sc->acpi_stype == POWER_STYPE_SUSPEND_TO_IDLE) + state = ACPI_STATE_S3; + else + state = acpi_stype_to_sstate(sc, sc->acpi_stype); + if (state == ACPI_STATE_UNKNOWN) + return (ENOENT); + return (acpi_device_pwr_for_sleep_sxd(bus, handle, state, dstate)); } /* Callback arg for our implementation of walking the namespace. */ @@ -2558,11 +2616,54 @@ acpi_fake_objhandler(ACPI_HANDLE h, void *data) { } +/* + * Simple wrapper around AcpiEnterSleepStatePrep() printing diagnostic on error. + */ +static ACPI_STATUS +acpi_EnterSleepStatePrep(device_t acpi_dev, UINT8 SleepState) +{ + ACPI_STATUS status; + + status = AcpiEnterSleepStatePrep(SleepState); + if (ACPI_FAILURE(status)) + device_printf(acpi_dev, + "AcpiEnterSleepStatePrep(%u) failed - %s\n", + SleepState, + AcpiFormatException(status)); + return (status); +} + +/* Return from this function indicates failure. */ +static void +acpi_poweroff(device_t acpi_dev) +{ + register_t intr; + ACPI_STATUS status; + + device_printf(acpi_dev, "Powering system off...\n"); + status = acpi_EnterSleepStatePrep(acpi_dev, ACPI_STATE_S5); + if (ACPI_FAILURE(status)) { + device_printf(acpi_dev, "Power-off preparation failed! - %s\n", + AcpiFormatException(status)); + return; + } + intr = intr_disable(); + status = AcpiEnterSleepState(ACPI_STATE_S5); + if (ACPI_FAILURE(status)) { + intr_restore(intr); + device_printf(acpi_dev, "Power-off failed! - %s\n", + AcpiFormatException(status)); + } else { + DELAY(1000000); + intr_restore(intr); + device_printf(acpi_dev, "Power-off failed! - timeout\n"); + } +} + static void acpi_shutdown_final(void *arg, int howto) { struct acpi_softc *sc = (struct acpi_softc *)arg; - register_t intr; ACPI_STATUS status; /* @@ -2571,24 +2672,7 @@ acpi_shutdown_final(void *arg, int howto) * an AP. */ if ((howto & RB_POWEROFF) != 0) { - status = AcpiEnterSleepStatePrep(ACPI_STATE_S5); - if (ACPI_FAILURE(status)) { - device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n", - AcpiFormatException(status)); - return; - } - device_printf(sc->acpi_dev, "Powering system off\n"); - intr = intr_disable(); - status = AcpiEnterSleepState(ACPI_STATE_S5); - if (ACPI_FAILURE(status)) { - intr_restore(intr); - device_printf(sc->acpi_dev, "power-off failed - %s\n", - AcpiFormatException(status)); - } else { - DELAY(1000000); - intr_restore(intr); - device_printf(sc->acpi_dev, "power-off failed - timeout\n"); - } + acpi_poweroff(sc->acpi_dev); } else if ((howto & RB_HALT) == 0 && sc->acpi_handle_reboot) { /* Reboot using the reset register. */ status = AcpiReset(); @@ -3315,7 +3399,8 @@ acpi_ReqSleepState(struct acpi_softc *sc, enum power_stype stype) return (0); #else - /* This platform does not support acpi suspend/resume. */ + device_printf(sc->acpi_dev, "ACPI suspend not supported on this platform " + "(TODO suspend to idle should be, however)\n"); return (EOPNOTSUPP); #endif } @@ -3330,13 +3415,13 @@ acpi_ReqSleepState(struct acpi_softc *sc, enum power_stype stype) int acpi_AckSleepState(struct apm_clone_data *clone, int error) { + struct acpi_softc *sc = clone->acpi_sc; + #if defined(__amd64__) || defined(__i386__) - struct acpi_softc *sc; int ret, sleeping; /* If no pending sleep type, return an error. */ ACPI_LOCK(acpi); - sc = clone->acpi_sc; if (sc->acpi_next_stype == POWER_STYPE_AWAKE) { ACPI_UNLOCK(acpi); return (ENXIO); @@ -3379,7 +3464,8 @@ acpi_AckSleepState(struct apm_clone_data *clone, int error) } return (ret); #else - /* This platform does not support acpi suspend/resume. */ + device_printf(sc->acpi_dev, "ACPI suspend not supported on this platform " + "(TODO suspend to idle should be, however)\n"); return (EOPNOTSUPP); #endif } @@ -3418,27 +3504,133 @@ acpi_sleep_disable(struct acpi_softc *sc) } enum acpi_sleep_state { - ACPI_SS_NONE, - ACPI_SS_GPE_SET, - ACPI_SS_DEV_SUSPEND, - ACPI_SS_SLP_PREP, - ACPI_SS_SLEPT, + ACPI_SS_NONE = 0, + ACPI_SS_GPE_SET = 1 << 0, + ACPI_SS_DEV_SUSPEND = 1 << 1, + ACPI_SS_SLP_PREP = 1 << 2, + ACPI_SS_SLEPT = 1 << 3, }; +static void +do_standby(struct acpi_softc *sc, enum acpi_sleep_state *slp_state, + register_t rflags) +{ + ACPI_STATUS status; + + status = AcpiEnterSleepState(sc->acpi_standby_sx); + intr_restore(rflags); + AcpiLeaveSleepStatePrep(sc->acpi_standby_sx); + if (ACPI_FAILURE(status)) { + device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", + AcpiFormatException(status)); + return; + } + *slp_state |= ACPI_SS_SLEPT; +} + +static void +do_sleep(struct acpi_softc *sc, enum acpi_sleep_state *slp_state, + register_t rflags, int state) +{ + int sleep_result; + ACPI_EVENT_STATUS power_button_status; + + MPASS(state == ACPI_STATE_S3 || state == ACPI_STATE_S4); + + sleep_result = acpi_sleep_machdep(sc, state); + acpi_wakeup_machdep(sc, state, sleep_result, 0); + + if (sleep_result == 1 && state == ACPI_STATE_S3) { + /* + * XXX According to ACPI specification SCI_EN bit should be restored + * by ACPI platform (BIOS, firmware) to its pre-sleep state. + * Unfortunately some BIOSes fail to do that and that leads to + * unexpected and serious consequences during wake up like a system + * getting stuck in SMI handlers. + * This hack is picked up from Linux, which claims that it follows + * Windows behavior. + */ + AcpiWriteBitRegister(ACPI_BITREG_SCI_ENABLE, ACPI_ENABLE_EVENT); + + /* + * Prevent misinterpretation of the wakeup by power button + * as a request for power off. + * Ideally we should post an appropriate wakeup event, + * perhaps using acpi_event_power_button_wake or alike. + * + * Clearing of power button status after wakeup is mandated + * by ACPI specification in section "Fixed Power Button". + * + * XXX As of ACPICA 20121114 AcpiGetEventStatus provides + * status as 0/1 corresponding to inactive/active despite + * its type being ACPI_EVENT_STATUS. In other words, + * we should not test for ACPI_EVENT_FLAG_SET for time being. + */ + if (ACPI_SUCCESS(AcpiGetEventStatus(ACPI_EVENT_POWER_BUTTON, + &power_button_status)) && power_button_status != 0) { + AcpiClearEvent(ACPI_EVENT_POWER_BUTTON); + device_printf(sc->acpi_dev, "cleared fixed power button status\n"); + } + } + + intr_restore(rflags); + + /* call acpi_wakeup_machdep() again with interrupt enabled */ + acpi_wakeup_machdep(sc, state, sleep_result, 1); + + AcpiLeaveSleepStatePrep(state); + + if (sleep_result == -1) + return; + + /* Re-enable ACPI hardware on wakeup from sleep state 4. */ + if (state == ACPI_STATE_S4) + AcpiEnable(); + *slp_state |= ACPI_SS_SLEPT; +} + +#if defined(__i386__) || defined(__amd64__) +static void +do_idle(struct acpi_softc *sc, enum acpi_sleep_state *slp_state, + register_t rflags) +{ + + intr_suspend(); + + /* + * The CPU will exit idle when interrupted, so we want to minimize the + * number of interrupts it can receive while idle. We do this by only + * allowing SCI (system control interrupt) interrupts, which are used by + * the ACPI firmware to send wake GPEs to the OS. + * + * XXX We might still receive other spurious non-wake GPEs from noisy + * devices that can't be disabled, so this will need to end up being a + * suspend-to-idle loop which, when breaking out of idle, will check the + * reason for the wakeup and immediately idle the CPU again if it was not a + * proper wake event. + */ + intr_enable_src(AcpiGbl_FADT.SciInterrupt); + + cpu_idle(0); + + intr_resume(false); + intr_restore(rflags); + *slp_state |= ACPI_SS_SLEPT; +} +#endif + /* * Enter the desired system sleep state. * - * Currently we support S1-S5 but S4 is only S4BIOS + * Currently we support S1-S5 and suspend-to-idle, but S4 is only S4BIOS. */ static ACPI_STATUS acpi_EnterSleepState(struct acpi_softc *sc, enum power_stype stype) { register_t intr; ACPI_STATUS status; - ACPI_EVENT_STATUS power_button_status; enum acpi_sleep_state slp_state; int acpi_sstate; - int sleep_result; ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, stype); @@ -3498,7 +3690,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, enum power_stype stype) /* Enable any GPEs as appropriate and requested by the user. */ acpi_wake_prep_walk(sc, stype); - slp_state = ACPI_SS_GPE_SET; + slp_state |= ACPI_SS_GPE_SET; /* * Inform all devices that we are going to sleep. If at least one @@ -3509,113 +3701,77 @@ acpi_EnterSleepState(struct acpi_softc *sc, enum power_stype stype) * bus interface does not provide for this. */ if (DEVICE_SUSPEND(root_bus) != 0) { - device_printf(sc->acpi_dev, "device_suspend failed\n"); - goto backout; + device_printf(sc->acpi_dev, "device_suspend failed\n"); + goto backout; } - slp_state = ACPI_SS_DEV_SUSPEND; + EVENTHANDLER_INVOKE(acpi_post_dev_suspend, stype); + slp_state |= ACPI_SS_DEV_SUSPEND; - status = AcpiEnterSleepStatePrep(acpi_sstate); - if (ACPI_FAILURE(status)) { - device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n", - AcpiFormatException(status)); - goto backout; + if (stype != POWER_STYPE_SUSPEND_TO_IDLE) { + status = acpi_EnterSleepStatePrep(sc->acpi_dev, acpi_sstate); + if (ACPI_FAILURE(status)) + goto backout; + slp_state |= ACPI_SS_SLP_PREP; } - slp_state = ACPI_SS_SLP_PREP; if (sc->acpi_sleep_delay > 0) DELAY(sc->acpi_sleep_delay * 1000000); suspendclock(); intr = intr_disable(); - if (stype != POWER_STYPE_STANDBY) { - sleep_result = acpi_sleep_machdep(sc, acpi_sstate); - acpi_wakeup_machdep(sc, acpi_sstate, sleep_result, 0); - - /* - * XXX According to ACPI specification SCI_EN bit should be restored - * by ACPI platform (BIOS, firmware) to its pre-sleep state. - * Unfortunately some BIOSes fail to do that and that leads to - * unexpected and serious consequences during wake up like a system - * getting stuck in SMI handlers. - * This hack is picked up from Linux, which claims that it follows - * Windows behavior. - */ - if (sleep_result == 1 && stype != POWER_STYPE_HIBERNATE) - AcpiWriteBitRegister(ACPI_BITREG_SCI_ENABLE, ACPI_ENABLE_EVENT); - - if (sleep_result == 1 && stype == POWER_STYPE_SUSPEND_TO_MEM) { - /* - * Prevent mis-interpretation of the wakeup by power button - * as a request for power off. - * Ideally we should post an appropriate wakeup event, - * perhaps using acpi_event_power_button_wake or alike. - * - * Clearing of power button status after wakeup is mandated - * by ACPI specification in section "Fixed Power Button". - * - * XXX As of ACPICA 20121114 AcpiGetEventStatus provides - * status as 0/1 corressponding to inactive/active despite - * its type being ACPI_EVENT_STATUS. In other words, - * we should not test for ACPI_EVENT_FLAG_SET for time being. - */ - if (ACPI_SUCCESS(AcpiGetEventStatus(ACPI_EVENT_POWER_BUTTON, - &power_button_status)) && power_button_status != 0) { - AcpiClearEvent(ACPI_EVENT_POWER_BUTTON); - device_printf(sc->acpi_dev, - "cleared fixed power button status\n"); - } - } - - intr_restore(intr); - - /* call acpi_wakeup_machdep() again with interrupt enabled */ - acpi_wakeup_machdep(sc, acpi_sstate, sleep_result, 1); - - AcpiLeaveSleepStatePrep(acpi_sstate); - - if (sleep_result == -1) - goto backout; - - /* Re-enable ACPI hardware on wakeup from hibernate. */ - if (stype == POWER_STYPE_HIBERNATE) - AcpiEnable(); - } else { - status = AcpiEnterSleepState(acpi_sstate); - intr_restore(intr); - AcpiLeaveSleepStatePrep(acpi_sstate); - if (ACPI_FAILURE(status)) { - device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", - AcpiFormatException(status)); - goto backout; - } + switch (stype) { + case POWER_STYPE_STANDBY: + do_standby(sc, &slp_state, intr); + break; + case POWER_STYPE_SUSPEND_TO_MEM: + case POWER_STYPE_HIBERNATE: + do_sleep(sc, &slp_state, intr, acpi_sstate); + break; + case POWER_STYPE_SUSPEND_TO_IDLE: +#if defined(__i386__) || defined(__amd64__) + do_idle(sc, &slp_state, intr); + break; +#endif + case POWER_STYPE_AWAKE: + case POWER_STYPE_POWEROFF: + case POWER_STYPE_COUNT: + case POWER_STYPE_UNKNOWN: + __unreachable(); } - slp_state = ACPI_SS_SLEPT; + resumeclock(); /* * Back out state according to how far along we got in the suspend * process. This handles both the error and success cases. */ backout: - if (slp_state >= ACPI_SS_SLP_PREP) - resumeclock(); - if (slp_state >= ACPI_SS_GPE_SET) { + if ((slp_state & ACPI_SS_GPE_SET) != 0) { acpi_wake_prep_walk(sc, stype); sc->acpi_stype = POWER_STYPE_AWAKE; + slp_state &= ~ACPI_SS_GPE_SET; } - if (slp_state >= ACPI_SS_DEV_SUSPEND) + if ((slp_state & ACPI_SS_DEV_SUSPEND) != 0) { + EVENTHANDLER_INVOKE(acpi_pre_dev_resume, stype); DEVICE_RESUME(root_bus); - if (slp_state >= ACPI_SS_SLP_PREP) + slp_state &= ~ACPI_SS_DEV_SUSPEND; + } + if ((slp_state & ACPI_SS_SLP_PREP) != 0) { AcpiLeaveSleepState(acpi_sstate); - if (slp_state >= ACPI_SS_SLEPT) { + slp_state &= ~ACPI_SS_SLP_PREP; + } + if ((slp_state & ACPI_SS_SLEPT) != 0) { #if defined(__i386__) || defined(__amd64__) /* NB: we are still using ACPI timecounter at this point. */ resume_TSC(); #endif acpi_resync_clock(sc); acpi_enable_fixed_events(sc); + slp_state &= ~ACPI_SS_SLEPT; } sc->acpi_next_stype = POWER_STYPE_AWAKE; + MPASS(slp_state == ACPI_SS_NONE); + bus_topo_unlock(); #ifdef EARLY_AP_STARTUP @@ -3815,7 +3971,7 @@ acpi_wake_sysctl_walk(device_t dev) for (i = 0; i < numdevs; i++) { child = devlist[i]; acpi_wake_sysctl_walk(child); - if (!device_is_attached(child)) + if (!device_is_attached(child) || !acpi_has_flags(child)) continue; status = AcpiEvaluateObject(acpi_get_handle(child), "_PRW", NULL, NULL); if (ACPI_SUCCESS(status)) { @@ -3960,7 +4116,7 @@ acpi_system_eventhandler_sleep(void *arg, enum power_stype stype) ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, stype); /* Check if button action is disabled or unknown. */ - if (stype == ACPI_STATE_UNKNOWN) + if (stype == POWER_STYPE_UNKNOWN) return; /* @@ -4242,6 +4398,21 @@ acpi_deregister_ioctl(u_long cmd, acpi_ioctl_fn fn) ACPI_UNLOCK(acpi); } +void +acpi_deregister_ioctls(acpi_ioctl_fn fn) +{ + struct acpi_ioctl_hook *hp, *thp; + + ACPI_LOCK(acpi); + TAILQ_FOREACH_SAFE(hp, &acpi_ioctl_hooks, link, thp) { + if (hp->fn == fn) { + TAILQ_REMOVE(&acpi_ioctl_hooks, hp, link); + free(hp, M_ACPIDEV); + } + } + ACPI_UNLOCK(acpi); +} + static int acpiopen(struct cdev *dev, int flag, int fmt, struct thread *td) { @@ -4317,6 +4488,25 @@ acpiioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *t } static int +acpi_s4bios_sysctl(SYSCTL_HANDLER_ARGS) +{ + struct acpi_softc *const sc = arg1; + bool val; + int error; + + val = sc->acpi_s4bios; + error = sysctl_handle_bool(oidp, &val, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + + if (val && !sc->acpi_s4bios_supported) + return (EOPNOTSUPP); + sc->acpi_s4bios = val; + + return (0); +} + +static int acpi_sname_to_sstate(const char *sname) { int sstate; @@ -4438,9 +4628,9 @@ acpi_stype_sysctl(SYSCTL_HANDLER_ARGS) sstate = acpi_sname_to_sstate(name); if (sstate < 0) return (EINVAL); - printf("warning: this sysctl expects a sleep type, but an ACPI " - "S-state has been passed to it. This functionality is " - "deprecated; see acpi(4).\n"); + printf("warning: the 'hw.acpi.%s' sysctl expects a sleep type, but " + "an ACPI S-state has been passed to it. This functionality " + "is deprecated; see acpi(4).\n", oidp->oid_name); MPASS(sstate < ACPI_S_STATE_COUNT); if (acpi_supported_sstates[sstate] == false) return (EOPNOTSUPP); @@ -4514,6 +4704,7 @@ static struct debugtag dbg_layer[] = { {"ACPI_FAN", ACPI_FAN}, {"ACPI_POWERRES", ACPI_POWERRES}, {"ACPI_PROCESSOR", ACPI_PROCESSOR}, + {"ACPI_SPMC", ACPI_SPMC}, {"ACPI_THERMAL", ACPI_THERMAL}, {"ACPI_TIMER", ACPI_TIMER}, {"ACPI_ALL_DRIVERS", ACPI_ALL_DRIVERS}, @@ -4798,6 +4989,65 @@ acpi_reset_interfaces(device_t dev) } acpi_free_interfaces(&list); } + + /* + * Apple Mac hardware quirk: install Darwin OSI. + * + * On Apple hardware, install the Darwin OSI and remove the Windows OSI + * to match Linux behavior. + * + * This is required for dual-GPU MacBook Pro systems + * (Intel iGPU + AMD/NVIDIA dGPU) where the iGPU is hidden when the + * firmware doesn't see Darwin OSI, but it also unlocks additional ACPI + * support on non-MacBook Pro Apple platforms. + * + * Apple's ACPI firmware checks _OSI("Darwin") and sets OSYS=10000 + * for macOS. Many device methods use OSDW() which checks OSYS==10000 + * for macOS-specific behavior including GPU visibility and power + * management. + * + * Linux enables Darwin OSI by default on Apple hardware and disables + * all Windows OSI strings (drivers/acpi/osi.c). Users can override + * this behavior with acpi_osi=!Darwin to get Windows-like behavior, + * in general, but this logic makes that process unnecessary. + * + * Detect Apple via SMBIOS and enable Darwin while disabling Windows + * vendor strings. This makes both GPUs visible on dual-GPU MacBook Pro + * systems (Intel iGPU + AMD dGPU) and unlocks full platform + * ACPI support. + */ + if (acpi_apple_darwin_osi) { + char *vendor = kern_getenv("smbios.system.maker"); + if (vendor != NULL) { + if (strcmp(vendor, "Apple Inc.") == 0 || + strcmp(vendor, "Apple Computer, Inc.") == 0) { + /* Disable all other OSI vendor strings. */ + status = AcpiUpdateInterfaces( + ACPI_DISABLE_ALL_VENDOR_STRINGS); + if (ACPI_SUCCESS(status)) { + /* Install Darwin OSI */ + status = AcpiInstallInterface("Darwin"); + } + if (bootverbose) { + if (ACPI_SUCCESS(status)) { + device_printf(dev, + "disabled non-Darwin OSI & " + "installed Darwin OSI\n"); + } else { + device_printf(dev, + "could not install " + "Darwin OSI: %s\n", + AcpiFormatException(status)); + } + } + } else if (bootverbose) { + device_printf(dev, + "Not installing Darwin OSI on unsupported platform: %s\n", + vendor); + } + freeenv(vendor); + } + } } static int diff --git a/sys/dev/acpica/acpi_battery.c b/sys/dev/acpica/acpi_battery.c index cfd8261d5eab..f1eebda705c1 100644 --- a/sys/dev/acpica/acpi_battery.c +++ b/sys/dev/acpica/acpi_battery.c @@ -531,13 +531,7 @@ acpi_battery_init(void) out: if (error) { - acpi_deregister_ioctl(ACPIIO_BATT_GET_UNITS, acpi_battery_ioctl); - acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO, acpi_battery_ioctl); - acpi_deregister_ioctl(ACPIIO_BATT_GET_BATTINFO_V1, acpi_battery_ioctl); - acpi_deregister_ioctl(ACPIIO_BATT_GET_BIF, acpi_battery_ioctl); - acpi_deregister_ioctl(ACPIIO_BATT_GET_BIX, acpi_battery_ioctl); - acpi_deregister_ioctl(ACPIIO_BATT_GET_BST, acpi_battery_ioctl); - acpi_deregister_ioctl(ACPIIO_BATT_GET_BST_V1, acpi_battery_ioctl); + acpi_deregister_ioctls(acpi_battery_ioctl); } return (error); } diff --git a/sys/dev/acpica/acpi_spmc.c b/sys/dev/acpica/acpi_spmc.c new file mode 100644 index 000000000000..03944800327d --- /dev/null +++ b/sys/dev/acpica/acpi_spmc.c @@ -0,0 +1,656 @@ +/* + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024-2026 The FreeBSD Foundation + * + * This software was developed by Aymeric Wibo <obiwac@freebsd.org> + * under sponsorship from the FreeBSD Foundation. + */ + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/eventhandler.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/uuid.h> + +#include <machine/_inttypes.h> + +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> + +#include <dev/acpica/acpivar.h> + +/* Hooks for the ACPI CA debugging infrastructure */ +#define _COMPONENT ACPI_SPMC +ACPI_MODULE_NAME("SPMC") + +static SYSCTL_NODE(_debug_acpi, OID_AUTO, spmc, CTLFLAG_RD | CTLFLAG_MPSAFE, + NULL, "SPMC debugging"); + +static char *spmc_ids[] = { + "PNP0D80", + NULL +}; + +enum intel_dsm_index { + DSM_ENUM_FUNCTIONS = 0, + DSM_GET_DEVICE_CONSTRAINTS = 1, + DSM_GET_CRASH_DUMP_DEVICE = 2, + DSM_DISPLAY_OFF_NOTIF = 3, + DSM_DISPLAY_ON_NOTIF = 4, + DSM_ENTRY_NOTIF = 5, + DSM_EXIT_NOTIF = 6, + /* Only for Microsoft DSM set. */ + DSM_MODERN_ENTRY_NOTIF = 7, + DSM_MODERN_EXIT_NOTIF = 8, + DSM_MODERN_TURN_ON_DISPLAY = 9, +}; + +enum amd_dsm_index { + AMD_DSM_ENUM_FUNCTIONS = 0, + AMD_DSM_GET_DEVICE_CONSTRAINTS = 1, + AMD_DSM_ENTRY_NOTIF = 2, + AMD_DSM_EXIT_NOTIF = 3, + AMD_DSM_DISPLAY_OFF_NOTIF = 4, + AMD_DSM_DISPLAY_ON_NOTIF = 5, +}; + +enum dsm_set_flags { + DSM_SET_INTEL = 1 << 0, + DSM_SET_MS = 1 << 1, + DSM_SET_AMD = 1 << 2, +}; + +struct dsm_set { + enum dsm_set_flags flag; + const char *name; + int revision; + struct uuid uuid; + uint64_t dsms_supported; + uint64_t dsms_expected; + uint64_t extra_dsms; +}; + +static struct dsm_set intel_dsm_set = { + .flag = DSM_SET_INTEL, + .name = "Intel", + /* + * XXX Linux uses 1 for the revision on Intel DSMs, but doesn't explain + * why. The commit that introduces this links to a document mentioning + * revision 0, so default this to 0. + * + * The debug.acpi.spmc.intel_dsm_revision sysctl may be used to configure + * this just in case. + */ + .revision = 0, + .uuid = { /* c4eb40a0-6cd2-11e2-bcfd-0800200c9a66 */ + 0xc4eb40a0, 0x6cd2, 0x11e2, 0xbc, 0xfd, + {0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66}, + }, + .dsms_expected = (1 << DSM_GET_DEVICE_CONSTRAINTS) | + (1 << DSM_DISPLAY_OFF_NOTIF) | (1 << DSM_DISPLAY_ON_NOTIF) | + (1 << DSM_ENTRY_NOTIF) | (1 << DSM_EXIT_NOTIF), +}; + +SYSCTL_INT(_debug_acpi_spmc, OID_AUTO, intel_dsm_revision, CTLFLAG_RW, + &intel_dsm_set.revision, 0, + "Revision to use when evaluating Intel SPMC DSMs"); + +static struct dsm_set ms_dsm_set = { + .flag = DSM_SET_MS, + .name = "Microsoft", + .revision = 0, + .uuid = { /* 11e00d56-ce64-47ce-837b-1f898f9aa461 */ + 0x11e00d56, 0xce64, 0x47ce, 0x83, 0x7b, + {0x1f, 0x89, 0x8f, 0x9a, 0xa4, 0x61}, + }, + .dsms_expected = (1 << DSM_DISPLAY_OFF_NOTIF) | + (1 << DSM_DISPLAY_ON_NOTIF) | (1 << DSM_ENTRY_NOTIF) | + (1 << DSM_EXIT_NOTIF) | (1 << DSM_MODERN_ENTRY_NOTIF) | + (1 << DSM_MODERN_EXIT_NOTIF), + .extra_dsms = (1 << DSM_MODERN_TURN_ON_DISPLAY), +}; + +static struct dsm_set amd_dsm_set = { + .flag = DSM_SET_AMD, + .name = "AMD", + /* + * XXX Linux uses 0 for the revision on AMD DSMs, but at least on the + * Framework 13 AMD 7040 series, the enum functions DSM only returns a + * function mask that covers all the DSMs we need to call when called + * with revision 2. + * + * The debug.acpi.spmc.amd_dsm_revision sysctl may be used to configure + * this just in case. + */ + .revision = 2, + .uuid = { /* e3f32452-febc-43ce-9039-932122d37721 */ + 0xe3f32452, 0xfebc, 0x43ce, 0x90, 0x39, + {0x93, 0x21, 0x22, 0xd3, 0x77, 0x21}, + }, + .dsms_expected = (1 << AMD_DSM_GET_DEVICE_CONSTRAINTS) | + (1 << AMD_DSM_ENTRY_NOTIF) | (1 << AMD_DSM_EXIT_NOTIF) | + (1 << AMD_DSM_DISPLAY_OFF_NOTIF) | (1 << AMD_DSM_DISPLAY_ON_NOTIF), +}; + +SYSCTL_INT(_debug_acpi_spmc, OID_AUTO, amd_dsm_revision, CTLFLAG_RW, + &amd_dsm_set.revision, 0, "Revision to use when evaluating AMD SPMC DSMs"); + +union dsm_index { + int i; + enum intel_dsm_index regular; + enum amd_dsm_index amd; +}; + +struct acpi_spmc_constraint { + bool enabled; + char *name; + int min_d_state; + ACPI_HANDLE handle; + + /* Unused, spec only. */ + uint64_t lpi_uid; + uint64_t min_dev_specific_state; + + /* Unused, AMD only. */ + uint64_t function_states; +}; + +struct acpi_spmc_softc { + device_t dev; + ACPI_HANDLE handle; + ACPI_OBJECT *obj; + enum dsm_set_flags dsm_sets; + + struct eventhandler_entry *eh_suspend; + struct eventhandler_entry *eh_resume; + + bool constraints_populated; + size_t constraint_count; + struct acpi_spmc_constraint *constraints; +}; + +static void acpi_spmc_check_dsm_set(struct acpi_spmc_softc *sc, + ACPI_HANDLE handle, struct dsm_set *dsm_set); +static int acpi_spmc_get_constraints(device_t dev); +static void acpi_spmc_free_constraints(struct acpi_spmc_softc *sc); + +static void acpi_spmc_suspend(device_t dev, enum power_stype stype); +static void acpi_spmc_resume(device_t dev, enum power_stype stype); + +static int +acpi_spmc_probe(device_t dev) +{ + char *name; + ACPI_HANDLE handle; + struct acpi_spmc_softc *sc; + + /* Check that this is an enabled device. */ + if (acpi_get_type(dev) != ACPI_TYPE_DEVICE || acpi_disabled("spmc")) + return (ENXIO); + + if (ACPI_ID_PROBE(device_get_parent(dev), dev, spmc_ids, &name) > 0) + return (ENXIO); + + if (device_get_unit(dev) > 0) { + device_printf(dev, "shouldn't have more than one SPMC"); + return (ENXIO); + } + + handle = acpi_get_handle(dev); + /* ACPI_ID_PROBE() above cannot succeed without a handle. */ + MPASS(handle != NULL); + + sc = device_get_softc(dev); + sc->dev = dev; + + /* Check which sets of DSMs are supported. */ + sc->dsm_sets = 0; + + acpi_spmc_check_dsm_set(sc, handle, &intel_dsm_set); + acpi_spmc_check_dsm_set(sc, handle, &ms_dsm_set); + acpi_spmc_check_dsm_set(sc, handle, &amd_dsm_set); + + if (sc->dsm_sets == 0) + return (ENXIO); + + device_set_descf(dev, "System Power Management Controller " + "(DSM sets 0x%x)", sc->dsm_sets); + + return (0); +} + +static int +acpi_spmc_attach(device_t dev) +{ + struct acpi_spmc_softc *sc = device_get_softc(dev); + + sc->handle = acpi_get_handle(dev); + if (sc->handle == NULL) + return (ENXIO); + + sc->constraints_populated = false; + sc->constraint_count = 0; + sc->constraints = NULL; + + /* Get device constraints. We can only call this once so do this now. */ + acpi_spmc_get_constraints(dev); + + sc->eh_suspend = EVENTHANDLER_REGISTER(acpi_post_dev_suspend, + acpi_spmc_suspend, dev, 0); + sc->eh_resume = EVENTHANDLER_REGISTER(acpi_pre_dev_resume, + acpi_spmc_resume, dev, 0); + + return (0); +} + +static int +acpi_spmc_detach(device_t dev) +{ + struct acpi_spmc_softc *sc = device_get_softc(dev); + + EVENTHANDLER_DEREGISTER(acpi_post_dev_suspend, sc->eh_suspend); + EVENTHANDLER_DEREGISTER(acpi_pre_dev_resume, sc->eh_resume); + + acpi_spmc_free_constraints(device_get_softc(dev)); + return (0); +} + +static void +acpi_spmc_check_dsm_set(struct acpi_spmc_softc *sc, ACPI_HANDLE handle, + struct dsm_set *dsm_set) +{ + uint64_t dsms_supported = acpi_DSMQuery(handle, + (uint8_t *)&dsm_set->uuid, dsm_set->revision); + const uint64_t min_dsms = dsm_set->dsms_expected; + const uint64_t max_dsms = min_dsms | dsm_set->extra_dsms; + + /* + * Check if DSM set supported at all. We do this by checking the + * existence of "enum functions". + */ + if ((dsms_supported & 1) == 0) + return; + dsms_supported &= ~1; + dsm_set->dsms_supported = dsms_supported; + sc->dsm_sets |= dsm_set->flag; + + if ((dsms_supported & min_dsms) != min_dsms) + device_printf(sc->dev, "DSM set %s does not support expected " + "DSMs (%#" PRIx64 " vs %#" PRIx64 "). " + "Some methods may fail.\n", + dsm_set->name, dsms_supported, min_dsms); + + if ((dsms_supported & ~max_dsms) != 0) + device_printf(sc->dev, "DSM set %s supports more DSMs than " + "expected (%#" PRIx64 " vs %#" PRIx64 ").\n", dsm_set->name, + dsms_supported, max_dsms); +} + +static void +acpi_spmc_free_constraints(struct acpi_spmc_softc *sc) +{ + for (size_t i = 0; i < sc->constraint_count; i++) + free(sc->constraints[i].name, M_TEMP); + sc->constraint_count = 0; + + free(sc->constraints, M_TEMP); + sc->constraints = NULL; +} + +static int +acpi_spmc_get_constraints_spec(struct acpi_spmc_softc *sc, ACPI_OBJECT *object) +{ + struct acpi_spmc_constraint *constraint; + int revision; + ACPI_OBJECT *constraint_obj; + ACPI_OBJECT *name_obj; + ACPI_OBJECT *detail; + ACPI_OBJECT *constraint_package; + + KASSERT(sc->constraints_populated == false, + ("constraints already populated")); + + sc->constraint_count = object->Package.Count; + sc->constraints = malloc(sc->constraint_count * sizeof *sc->constraints, + M_TEMP, M_WAITOK | M_ZERO); + + /* + * The value of sc->constraint_count can change during the loop, so + * iterate until object->Package.Count so we actually go over all + * elements in the package. + */ + for (size_t i = 0; i < object->Package.Count; i++) { + constraint_obj = &object->Package.Elements[i]; + constraint = &sc->constraints[i]; + + constraint->enabled = + constraint_obj->Package.Elements[1].Integer.Value; + + name_obj = &constraint_obj->Package.Elements[0]; + constraint->name = strdup(name_obj->String.Pointer, M_TEMP); + if (constraint->name == NULL) { + acpi_spmc_free_constraints(sc); + return (ENOMEM); + } + + detail = &constraint_obj->Package.Elements[2]; + /* + * The first element in the device constraint detail package is + * the revision, and should always be zero. + */ + revision = detail->Package.Elements[0].Integer.Value; + if (revision != 0) { + device_printf(sc->dev, "Unknown revision %d for " + "device constraint detail package\n", revision); + sc->constraint_count--; + continue; + } + + constraint_package = &detail->Package.Elements[1]; + + constraint->lpi_uid = + constraint_package->Package.Elements[0].Integer.Value; + constraint->min_d_state = + constraint_package->Package.Elements[1].Integer.Value; + constraint->min_dev_specific_state = + constraint_package->Package.Elements[2].Integer.Value; + } + + sc->constraints_populated = true; + return (0); +} + +static int +acpi_spmc_get_constraints_amd(struct acpi_spmc_softc *sc, ACPI_OBJECT *object) +{ + size_t constraint_count; + ACPI_OBJECT *constraint_obj; + ACPI_OBJECT *constraints; + struct acpi_spmc_constraint *constraint; + ACPI_OBJECT *name_obj; + + KASSERT(sc->constraints_populated == false, + ("constraints already populated")); + + /* + * First element in the package is unknown. + * Second element is the number of device constraints. + * Third element is the list of device constraints itself. + */ + constraint_count = object->Package.Elements[1].Integer.Value; + constraints = &object->Package.Elements[2]; + + if (constraints->Package.Count != constraint_count) { + device_printf(sc->dev, "constraint count mismatch (%d to %zu)\n", + constraints->Package.Count, constraint_count); + return (ENXIO); + } + + sc->constraint_count = constraint_count; + sc->constraints = malloc(constraint_count * sizeof *sc->constraints, + M_TEMP, M_WAITOK | M_ZERO); + + for (size_t i = 0; i < constraint_count; i++) { + /* Parse the constraint package. */ + constraint_obj = &constraints->Package.Elements[i]; + if (constraint_obj->Package.Count != 4) { + device_printf(sc->dev, "constraint %zu has %d elements\n", + i, constraint_obj->Package.Count); + acpi_spmc_free_constraints(sc); + return (ENXIO); + } + + constraint = &sc->constraints[i]; + constraint->enabled = + constraint_obj->Package.Elements[0].Integer.Value; + + name_obj = &constraint_obj->Package.Elements[1]; + constraint->name = strdup(name_obj->String.Pointer, M_TEMP); + if (constraint->name == NULL) { + acpi_spmc_free_constraints(sc); + return (ENOMEM); + } + + constraint->function_states = + constraint_obj->Package.Elements[2].Integer.Value; + constraint->min_d_state = + constraint_obj->Package.Elements[3].Integer.Value; + } + + sc->constraints_populated = true; + return (0); +} + +static int +acpi_spmc_get_constraints(device_t dev) +{ + struct acpi_spmc_softc *sc; + union dsm_index dsm_index; + struct dsm_set *dsm_set; + ACPI_STATUS status; + ACPI_BUFFER result; + ACPI_OBJECT *object; + bool is_amd; + int rv; + struct acpi_spmc_constraint *constraint; + + sc = device_get_softc(dev); + if (sc->constraints_populated) + return (0); + + /* The Microsoft DSM set doesn't have this DSM. */ + is_amd = (sc->dsm_sets & DSM_SET_AMD) != 0; + if (is_amd) { + dsm_set = &amd_dsm_set; + dsm_index.amd = AMD_DSM_GET_DEVICE_CONSTRAINTS; + } else { + dsm_set = &intel_dsm_set; + dsm_index.regular = DSM_GET_DEVICE_CONSTRAINTS; + } + + /* XXX It seems like this DSM fails if called more than once. */ + status = acpi_EvaluateDSMTyped(sc->handle, (uint8_t *)&dsm_set->uuid, + dsm_set->revision, dsm_index.i, NULL, &result, + ACPI_TYPE_PACKAGE); + if (ACPI_FAILURE(status)) { + device_printf(dev, "%s failed to call %s DSM %d (rev %d)\n", + __func__, dsm_set->name, dsm_index.i, dsm_set->revision); + return (ENXIO); + } + + object = (ACPI_OBJECT *)result.Pointer; + if (is_amd) + rv = acpi_spmc_get_constraints_amd(sc, object); + else + rv = acpi_spmc_get_constraints_spec(sc, object); + AcpiOsFree(object); + if (rv != 0) + return (rv); + + /* Get handles for each constraint device. */ + for (size_t i = 0; i < sc->constraint_count; i++) { + constraint = &sc->constraints[i]; + + status = acpi_GetHandleInScope(sc->handle, + __DECONST(char *, constraint->name), &constraint->handle); + if (ACPI_FAILURE(status)) { + device_printf(dev, "failed to get handle for %s\n", + constraint->name); + constraint->handle = NULL; + } + } + return (0); +} + +static void +acpi_spmc_check_constraints(struct acpi_spmc_softc *sc) +{ + bool violation = false; + + KASSERT(sc->constraints_populated, ("constraints not populated")); + for (size_t i = 0; i < sc->constraint_count; i++) { + struct acpi_spmc_constraint *constraint = &sc->constraints[i]; + + if (!constraint->enabled) + continue; + if (constraint->handle == NULL) + continue; + + ACPI_STATUS status = acpi_GetHandleInScope(sc->handle, + __DECONST(char *, constraint->name), &constraint->handle); + if (ACPI_FAILURE(status)) { + device_printf(sc->dev, "failed to get handle for %s\n", + constraint->name); + constraint->handle = NULL; + } + if (constraint->handle == NULL) + continue; + +#ifdef notyet + int d_state; + if (ACPI_FAILURE(acpi_pwr_get_state(constraint->handle, &d_state))) + continue; + if (d_state < constraint->min_d_state) { + device_printf(sc->dev, "constraint for device %s" + " violated (minimum D-state required was %s, actual" + " D-state is %s), might fail to enter LPI state\n", + constraint->name, + acpi_d_state_to_str(constraint->min_d_state), + acpi_d_state_to_str(d_state)); + violation = true; + } +#endif + } + if (!violation) + device_printf(sc->dev, + "all device power constraints respected!\n"); +} + +static void +acpi_spmc_run_dsm(device_t dev, struct dsm_set *dsm_set, int index) +{ + struct acpi_spmc_softc *sc; + ACPI_STATUS status; + ACPI_BUFFER result; + + sc = device_get_softc(dev); + + status = acpi_EvaluateDSMTyped(sc->handle, (uint8_t *)&dsm_set->uuid, + dsm_set->revision, index, NULL, &result, ACPI_TYPE_ANY); + + if (ACPI_FAILURE(status)) { + device_printf(dev, "%s failed to call %s DSM %d (rev %d)\n", + __func__, dsm_set->name, index, dsm_set->revision); + return; + } + + AcpiOsFree(result.Pointer); +} + +/* + * Try running the DSMs from all the DSM sets we have, as them failing costs us + * nothing, and it seems like on AMD platforms, both the AMD entry and Microsoft + * "modern" DSM's are required for it to enter modern standby. + * + * This is what Linux does too. + */ +static void +acpi_spmc_display_off_notif(device_t dev) +{ + struct acpi_spmc_softc *sc = device_get_softc(dev); + + if ((sc->dsm_sets & DSM_SET_INTEL) != 0) + acpi_spmc_run_dsm(dev, &intel_dsm_set, DSM_DISPLAY_OFF_NOTIF); + if ((sc->dsm_sets & DSM_SET_MS) != 0) + acpi_spmc_run_dsm(dev, &ms_dsm_set, DSM_DISPLAY_OFF_NOTIF); + if ((sc->dsm_sets & DSM_SET_AMD) != 0) + acpi_spmc_run_dsm(dev, &amd_dsm_set, AMD_DSM_DISPLAY_OFF_NOTIF); +} + +static void +acpi_spmc_display_on_notif(device_t dev) +{ + struct acpi_spmc_softc *sc = device_get_softc(dev); + + if ((sc->dsm_sets & DSM_SET_INTEL) != 0) + acpi_spmc_run_dsm(dev, &intel_dsm_set, DSM_DISPLAY_ON_NOTIF); + if ((sc->dsm_sets & DSM_SET_MS) != 0) + acpi_spmc_run_dsm(dev, &ms_dsm_set, DSM_DISPLAY_ON_NOTIF); + if ((sc->dsm_sets & DSM_SET_AMD) != 0) + acpi_spmc_run_dsm(dev, &amd_dsm_set, AMD_DSM_DISPLAY_ON_NOTIF); +} + +static void +acpi_spmc_entry_notif(device_t dev) +{ + struct acpi_spmc_softc *sc = device_get_softc(dev); + + acpi_spmc_check_constraints(sc); + + if ((sc->dsm_sets & DSM_SET_AMD) != 0) + acpi_spmc_run_dsm(dev, &amd_dsm_set, AMD_DSM_ENTRY_NOTIF); + if ((sc->dsm_sets & DSM_SET_MS) != 0) { + acpi_spmc_run_dsm(dev, &ms_dsm_set, DSM_MODERN_ENTRY_NOTIF); + acpi_spmc_run_dsm(dev, &ms_dsm_set, DSM_ENTRY_NOTIF); + } + if ((sc->dsm_sets & DSM_SET_INTEL) != 0) + acpi_spmc_run_dsm(dev, &intel_dsm_set, DSM_ENTRY_NOTIF); +} + +static void +acpi_spmc_exit_notif(device_t dev) +{ + struct acpi_spmc_softc *sc = device_get_softc(dev); + + if ((sc->dsm_sets & DSM_SET_INTEL) != 0) + acpi_spmc_run_dsm(dev, &intel_dsm_set, DSM_EXIT_NOTIF); + if ((sc->dsm_sets & DSM_SET_AMD) != 0) + acpi_spmc_run_dsm(dev, &amd_dsm_set, AMD_DSM_EXIT_NOTIF); + if ((sc->dsm_sets & DSM_SET_MS) != 0) { + acpi_spmc_run_dsm(dev, &ms_dsm_set, DSM_EXIT_NOTIF); + if (ms_dsm_set.dsms_supported & + (1 << DSM_MODERN_TURN_ON_DISPLAY)) + acpi_spmc_run_dsm(dev, &ms_dsm_set, + DSM_MODERN_TURN_ON_DISPLAY); + acpi_spmc_run_dsm(dev, &ms_dsm_set, DSM_MODERN_EXIT_NOTIF); + } +} + +static void +acpi_spmc_suspend(device_t dev, enum power_stype stype) +{ + if (stype != POWER_STYPE_SUSPEND_TO_IDLE) + return; + + acpi_spmc_display_off_notif(dev); + acpi_spmc_entry_notif(dev); +} + +static void +acpi_spmc_resume(device_t dev, enum power_stype stype) +{ + if (stype != POWER_STYPE_SUSPEND_TO_IDLE) + return; + + acpi_spmc_exit_notif(dev); + acpi_spmc_display_on_notif(dev); +} + +static device_method_t acpi_spmc_methods[] = { + DEVMETHOD(device_probe, acpi_spmc_probe), + DEVMETHOD(device_attach, acpi_spmc_attach), + DEVMETHOD(device_detach, acpi_spmc_detach), + DEVMETHOD_END +}; + +static driver_t acpi_spmc_driver = { + "acpi_spmc", + acpi_spmc_methods, + sizeof(struct acpi_spmc_softc), +}; + +DRIVER_MODULE_ORDERED(acpi_spmc, acpi, acpi_spmc_driver, NULL, NULL, SI_ORDER_ANY); +MODULE_DEPEND(acpi_spmc, acpi, 1, 1, 1); diff --git a/sys/dev/acpica/acpi_video.c b/sys/dev/acpica/acpi_video.c index 7a22c9dc0994..f949e14f58e6 100644 --- a/sys/dev/acpica/acpi_video.c +++ b/sys/dev/acpica/acpi_video.c @@ -176,7 +176,7 @@ static device_method_t acpi_video_methods[] = { DEVMETHOD(device_detach, acpi_video_detach), DEVMETHOD(device_resume, acpi_video_resume), DEVMETHOD(device_shutdown, acpi_video_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t acpi_video_driver = { diff --git a/sys/dev/acpica/acpiio.h b/sys/dev/acpica/acpiio.h index 63779d309951..4df049ed196a 100644 --- a/sys/dev/acpica/acpiio.h +++ b/sys/dev/acpica/acpiio.h @@ -205,6 +205,7 @@ union acpi_battery_ioctl_arg { typedef int (*acpi_ioctl_fn)(u_long cmd, caddr_t addr, void *arg); extern int acpi_register_ioctl(u_long cmd, acpi_ioctl_fn fn, void *arg); extern void acpi_deregister_ioctl(u_long cmd, acpi_ioctl_fn fn); +extern void acpi_deregister_ioctls(acpi_ioctl_fn fn); #endif #endif /* !_ACPIIO_H_ */ diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index 6db55b10570d..7bcac6239253 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -64,7 +64,8 @@ struct acpi_softc { enum power_stype acpi_lid_switch_stype; int acpi_standby_sx; - int acpi_s4bios; + bool acpi_s4bios; + bool acpi_s4bios_supported; int acpi_sleep_delay; int acpi_do_disable; @@ -191,6 +192,7 @@ extern struct mtx acpi_mutex; #define ACPI_THERMAL 0x01000000 #define ACPI_TIMER 0x02000000 #define ACPI_OEM 0x04000000 +#define ACPI_SPMC 0x08000000 /* * Constants for different interrupt models used with acpi_SetIntrModel(). @@ -275,42 +277,22 @@ extern int acpi_override_isa_irq_polarity; * interface compatibility with ISA drivers which can also * attach to ACPI. */ -#define ACPI_IVAR_HANDLE 0x100 -#define ACPI_IVAR_UNUSED 0x101 /* Unused/reserved. */ -#define ACPI_IVAR_PRIVATE 0x102 -#define ACPI_IVAR_FLAGS 0x103 -#define ACPI_IVAR_DOMAIN 0x104 +enum { + ACPI_IVAR_PRIVATE = 20, + ACPI_IVAR_DOMAIN, + ACPI_IVAR_HANDLE = BUS_IVARS_ACPI, + ACPI_IVAR_FLAGS +}; /* * ad_domain NUMA domain special value. */ #define ACPI_DEV_DOMAIN_UNKNOWN (-1) -/* - * Accessor functions for our ivars. Default value for BUS_READ_IVAR is - * (type) 0. The <sys/bus.h> accessor functions don't check return values. - */ -#define __ACPI_BUS_ACCESSOR(varp, var, ivarp, ivar, type) \ - \ -static __inline type varp ## _get_ ## var(device_t dev) \ -{ \ - uintptr_t v = 0; \ - BUS_READ_IVAR(device_get_parent(dev), dev, \ - ivarp ## _IVAR_ ## ivar, &v); \ - return ((type) v); \ -} \ - \ -static __inline void varp ## _set_ ## var(device_t dev, type t) \ -{ \ - uintptr_t v = (uintptr_t) t; \ - BUS_WRITE_IVAR(device_get_parent(dev), dev, \ - ivarp ## _IVAR_ ## ivar, v); \ -} - -__ACPI_BUS_ACCESSOR(acpi, handle, ACPI, HANDLE, ACPI_HANDLE) -__ACPI_BUS_ACCESSOR(acpi, private, ACPI, PRIVATE, void *) -__ACPI_BUS_ACCESSOR(acpi, flags, ACPI, FLAGS, int) -__ACPI_BUS_ACCESSOR(acpi, domain, ACPI, DOMAIN, int) +__BUS_ACCESSOR_DEFAULT(acpi, handle, ACPI, HANDLE, ACPI_HANDLE, NULL) +__BUS_ACCESSOR(acpi, private, ACPI, PRIVATE, void *) +__BUS_ACCESSOR(acpi, flags, ACPI, FLAGS, int) +__BUS_ACCESSOR(acpi, domain, ACPI, DOMAIN, int) void acpi_fake_objhandler(ACPI_HANDLE h, void *data); static __inline device_t @@ -481,12 +463,14 @@ UINT32 acpi_event_sleep_button_wake(void *context); #define ACPI_EVENT_PRI_DEFAULT 10000 #define ACPI_EVENT_PRI_LAST 20000 -typedef void (*acpi_event_handler_t)(void *, int); +typedef void (*acpi_event_handler_t)(void *, enum power_stype); EVENTHANDLER_DECLARE(acpi_sleep_event, acpi_event_handler_t); EVENTHANDLER_DECLARE(acpi_wakeup_event, acpi_event_handler_t); EVENTHANDLER_DECLARE(acpi_acad_event, acpi_event_handler_t); EVENTHANDLER_DECLARE(acpi_video_event, acpi_event_handler_t); +EVENTHANDLER_DECLARE(acpi_post_dev_suspend, acpi_event_handler_t); +EVENTHANDLER_DECLARE(acpi_pre_dev_resume, acpi_event_handler_t); /* Device power control. */ ACPI_STATUS acpi_pwr_wake_enable(ACPI_HANDLE consumer, int enable); @@ -523,10 +507,19 @@ acpi_d_state_to_str(int state) const char *strs[ACPI_D_STATE_COUNT] = {"D0", "D1", "D2", "D3hot", "D3cold"}; + if (state == ACPI_STATE_UNKNOWN) + return ("unknown D-state"); MPASS(state >= ACPI_STATE_D0 && state <= ACPI_D_STATES_MAX); return (strs[state]); } +static __inline bool +acpi_should_do_s4bios(struct acpi_softc *sc) +{ + MPASS(!sc->acpi_s4bios || sc->acpi_s4bios_supported); + return (sc->acpi_s4bios); +} + char *acpi_name(ACPI_HANDLE handle); int acpi_avoid(ACPI_HANDLE handle); int acpi_disabled(char *subsys); @@ -619,6 +612,19 @@ int acpi_pxm_parse(device_t dev); int acpi_map_pxm_to_vm_domainid(int pxm); bus_get_cpus_t acpi_get_cpus; +/* + * Hook for ACPI sleep routine. + */ +extern int (*acpi_prepare_sleep)(uint8_t state, uint32_t a, uint32_t b, + bool ext); + +static inline void +acpi_set_prepare_sleep( + int (*hook)(uint8_t state, uint32_t a, uint32_t b, bool ext)) +{ + acpi_prepare_sleep = hook; +} + #ifdef __aarch64__ /* * ARM specific ACPI interfaces, relating to IORT table. diff --git a/sys/dev/adb/adb_bus.c b/sys/dev/adb/adb_bus.c index 7f4bd8676fcf..52d38caf7a24 100644 --- a/sys/dev/adb/adb_bus.c +++ b/sys/dev/adb/adb_bus.c @@ -57,15 +57,15 @@ static device_method_t adb_bus_methods[] = { DEVMETHOD(device_probe, adb_bus_probe), DEVMETHOD(device_attach, adb_bus_attach), DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), + DEVMETHOD(device_resume, bus_generic_resume), /* Bus Interface */ - DEVMETHOD(bus_probe_nomatch, adb_probe_nomatch), - DEVMETHOD(bus_print_child, adb_print_child), + DEVMETHOD(bus_probe_nomatch, adb_probe_nomatch), + DEVMETHOD(bus_print_child, adb_print_child), - { 0, 0 }, + DEVMETHOD_END }; driver_t adb_driver = { diff --git a/sys/dev/adb/adb_buttons.c b/sys/dev/adb/adb_buttons.c index e003183f9e9d..14d96cc5a05c 100644 --- a/sys/dev/adb/adb_buttons.c +++ b/sys/dev/adb/adb_buttons.c @@ -67,7 +67,7 @@ static device_method_t abtn_methods[] = { /* ADB interface */ DEVMETHOD(adb_receive_packet, abtn_receive_packet), - { 0, 0 } + DEVMETHOD_END }; static driver_t abtn_driver = { diff --git a/sys/dev/adb/adb_kbd.c b/sys/dev/adb/adb_kbd.c index f1b8d3589be9..ce81da855efc 100644 --- a/sys/dev/adb/adb_kbd.c +++ b/sys/dev/adb/adb_kbd.c @@ -99,7 +99,7 @@ static device_method_t adb_kbd_methods[] = { /* ADB interface */ DEVMETHOD(adb_receive_packet, adb_kbd_receive_packet), - { 0, 0 } + DEVMETHOD_END }; static driver_t adb_kbd_driver = { diff --git a/sys/dev/adb/adb_mouse.c b/sys/dev/adb/adb_mouse.c index e89612abddb2..92fc512efb45 100644 --- a/sys/dev/adb/adb_mouse.c +++ b/sys/dev/adb/adb_mouse.c @@ -104,7 +104,7 @@ static device_method_t adb_mouse_methods[] = { /* ADB interface */ DEVMETHOD(adb_receive_packet, adb_mouse_receive_packet), - { 0, 0 } + DEVMETHOD_END }; static driver_t adb_mouse_driver = { diff --git a/sys/dev/agp/agp_ali.c b/sys/dev/agp/agp_ali.c index d0301f3a5c7e..b6dc2d34ddd4 100644 --- a/sys/dev/agp/agp_ali.c +++ b/sys/dev/agp/agp_ali.c @@ -253,7 +253,7 @@ static device_method_t agp_ali_methods[] = { DEVMETHOD(agp_free_memory, agp_generic_free_memory), DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), - { 0, 0 } + DEVMETHOD_END }; static driver_t agp_ali_driver = { diff --git a/sys/dev/agp/agp_amd.c b/sys/dev/agp/agp_amd.c index e7f1deed188d..368ea7e4de7d 100644 --- a/sys/dev/agp/agp_amd.c +++ b/sys/dev/agp/agp_amd.c @@ -390,7 +390,7 @@ static device_method_t agp_amd_methods[] = { DEVMETHOD(agp_free_memory, agp_generic_free_memory), DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), - { 0, 0 } + DEVMETHOD_END }; static driver_t agp_amd_driver = { diff --git a/sys/dev/agp/agp_amd64.c b/sys/dev/agp/agp_amd64.c index ff36200bd299..287e6fb7218c 100644 --- a/sys/dev/agp/agp_amd64.c +++ b/sys/dev/agp/agp_amd64.c @@ -498,7 +498,7 @@ static device_method_t agp_amd64_methods[] = { DEVMETHOD(agp_free_memory, agp_generic_free_memory), DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), - { 0, 0 } + DEVMETHOD_END }; static driver_t agp_amd64_driver = { diff --git a/sys/dev/agp/agp_apple.c b/sys/dev/agp/agp_apple.c index 48938044a5d6..d2a94cd654f7 100644 --- a/sys/dev/agp/agp_apple.c +++ b/sys/dev/agp/agp_apple.c @@ -278,7 +278,7 @@ static device_method_t agp_apple_methods[] = { DEVMETHOD(agp_free_memory, agp_generic_free_memory), DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), - { 0, 0 } + DEVMETHOD_END }; static driver_t agp_apple_driver = { diff --git a/sys/dev/agp/agp_ati.c b/sys/dev/agp/agp_ati.c index a383acdb89dc..667be51f48e8 100644 --- a/sys/dev/agp/agp_ati.c +++ b/sys/dev/agp/agp_ati.c @@ -362,7 +362,7 @@ static device_method_t agp_ati_methods[] = { DEVMETHOD(agp_free_memory, agp_generic_free_memory), DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), - { 0, 0 } + DEVMETHOD_END }; static driver_t agp_ati_driver = { diff --git a/sys/dev/agp/agp_i810.c b/sys/dev/agp/agp_i810.c index 371eac691916..fc27041d2e41 100644 --- a/sys/dev/agp/agp_i810.c +++ b/sys/dev/agp/agp_i810.c @@ -1234,7 +1234,7 @@ agp_gen4_install_gatt(device_t dev, const vm_size_t gtt_offset) struct agp_i810_softc *sc; sc = device_get_softc(dev); - pmap_change_attr((vm_offset_t)rman_get_virtual(sc->sc_res[0]) + + pmap_change_attr((char *)rman_get_virtual(sc->sc_res[0]) + gtt_offset, rman_get_size(sc->sc_res[0]) - gtt_offset, VM_MEMATTR_WRITE_COMBINING); agp_i830_install_gatt_init(sc); @@ -1913,7 +1913,7 @@ static device_method_t agp_i810_methods[] = { DEVMETHOD(agp_bind_memory, agp_i810_bind_memory), DEVMETHOD(agp_unbind_memory, agp_i810_unbind_memory), DEVMETHOD(agp_chipset_flush, agp_intel_gtt_chipset_flush), - { 0, 0 } + DEVMETHOD_END }; static driver_t agp_i810_driver = { diff --git a/sys/dev/agp/agp_intel.c b/sys/dev/agp/agp_intel.c index d8abd759dec6..0fec1f8a5201 100644 --- a/sys/dev/agp/agp_intel.c +++ b/sys/dev/agp/agp_intel.c @@ -419,7 +419,7 @@ static device_method_t agp_intel_methods[] = { DEVMETHOD(agp_free_memory, agp_generic_free_memory), DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), - { 0, 0 } + DEVMETHOD_END }; static driver_t agp_intel_driver = { diff --git a/sys/dev/agp/agp_nvidia.c b/sys/dev/agp/agp_nvidia.c index fa5b73023f59..8a24063f9d90 100644 --- a/sys/dev/agp/agp_nvidia.c +++ b/sys/dev/agp/agp_nvidia.c @@ -435,7 +435,7 @@ static device_method_t agp_nvidia_methods[] = { DEVMETHOD(agp_free_memory, agp_generic_free_memory), DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), - { 0, 0 } + DEVMETHOD_END }; static driver_t agp_nvidia_driver = { diff --git a/sys/dev/agp/agp_sis.c b/sys/dev/agp/agp_sis.c index 3df1ca19f478..daea60c5f30f 100644 --- a/sys/dev/agp/agp_sis.c +++ b/sys/dev/agp/agp_sis.c @@ -273,7 +273,7 @@ static device_method_t agp_sis_methods[] = { DEVMETHOD(agp_free_memory, agp_generic_free_memory), DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), - { 0, 0 } + DEVMETHOD_END }; static driver_t agp_sis_driver = { diff --git a/sys/dev/agp/agp_via.c b/sys/dev/agp/agp_via.c index 3948f1a96697..9d0871ae9b21 100644 --- a/sys/dev/agp/agp_via.c +++ b/sys/dev/agp/agp_via.c @@ -408,7 +408,7 @@ static device_method_t agp_via_methods[] = { DEVMETHOD(agp_free_memory, agp_generic_free_memory), DEVMETHOD(agp_bind_memory, agp_generic_bind_memory), DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory), - { 0, 0 } + DEVMETHOD_END }; static driver_t agp_via_driver = { diff --git a/sys/dev/ahci/ahci_pci.c b/sys/dev/ahci/ahci_pci.c index 2b4cb37275a6..ac1dbea9f6ae 100644 --- a/sys/dev/ahci/ahci_pci.c +++ b/sys/dev/ahci/ahci_pci.c @@ -294,6 +294,8 @@ static const struct { {0x91821b4b, 0x00, "Marvell 88SE9182", AHCI_Q_IOMMU_BUSWIDE}, {0x91831b4b, 0x00, "Marvell 88SS9183", AHCI_Q_IOMMU_BUSWIDE}, {0x91a01b4b, 0x00, "Marvell 88SE91Ax", AHCI_Q_IOMMU_BUSWIDE}, + {0x91a31b4b, 0x00, "Marvell 88SE9128", AHCI_Q_ALTSIG | + AHCI_Q_IOMMU_BUSWIDE}, {0x92151b4b, 0x00, "Marvell 88SE9215", 0}, {0x92201b4b, 0x00, "Marvell 88SE9220", AHCI_Q_ALTSIG | AHCI_Q_IOMMU_BUSWIDE}, @@ -523,7 +525,8 @@ ahci_pci_attach(device_t dev) * here, or the user has to change the mode in the BIOS * from RST to AHCI. */ - if (pci_get_vendor(dev) == 0x8086) { + if (pci_get_vendor(dev) == 0x8086 && + rman_get_size(ctlr->r_mem) >= 512 * 1024) { uint32_t vscap; vscap = ATA_INL(ctlr->r_mem, AHCI_VSCAP); diff --git a/sys/dev/aic7xxx/ahc_isa.c b/sys/dev/aic7xxx/ahc_isa.c index e096a9e5bb6d..37308b9dac6c 100644 --- a/sys/dev/aic7xxx/ahc_isa.c +++ b/sys/dev/aic7xxx/ahc_isa.c @@ -285,7 +285,7 @@ static device_method_t ahc_isa_device_methods[] = { DEVMETHOD(device_probe, ahc_isa_probe), DEVMETHOD(device_attach, ahc_isa_attach), DEVMETHOD(device_detach, ahc_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ahc_isa_driver = { diff --git a/sys/dev/aic7xxx/ahc_pci.c b/sys/dev/aic7xxx/ahc_pci.c index 8109a6714814..4c3cbc6a2422 100644 --- a/sys/dev/aic7xxx/ahc_pci.c +++ b/sys/dev/aic7xxx/ahc_pci.c @@ -41,7 +41,7 @@ static device_method_t ahc_pci_device_methods[] = { DEVMETHOD(device_probe, ahc_pci_probe), DEVMETHOD(device_attach, ahc_pci_attach), DEVMETHOD(device_detach, ahc_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ahc_pci_driver = { @@ -105,7 +105,7 @@ ahc_pci_attach(device_t dev) error = aic_dma_tag_create(ahc, /*parent*/bus_get_dma_tag(dev), /*alignment*/1, /*boundary*/0, (ahc->flags & AHC_39BIT_ADDRESSING) - ? 0x7FFFFFFFFFLL + ? (bus_addr_t)0x7FFFFFFFFFLL : BUS_SPACE_MAXADDR_32BIT, /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, /*filterarg*/NULL, diff --git a/sys/dev/aic7xxx/ahd_pci.c b/sys/dev/aic7xxx/ahd_pci.c index 6af7169b49ff..f53563e4ba40 100644 --- a/sys/dev/aic7xxx/ahd_pci.c +++ b/sys/dev/aic7xxx/ahd_pci.c @@ -41,7 +41,7 @@ static device_method_t ahd_pci_device_methods[] = { DEVMETHOD(device_probe, ahd_pci_probe), DEVMETHOD(device_attach, ahd_pci_attach), DEVMETHOD(device_detach, ahd_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ahd_pci_driver = { diff --git a/sys/dev/al_eth/al_eth.c b/sys/dev/al_eth/al_eth.c index f4fec7c6aa94..47d31c264f67 100644 --- a/sys/dev/al_eth/al_eth.c +++ b/sys/dev/al_eth/al_eth.c @@ -242,7 +242,7 @@ static device_method_t al_methods[] = { DEVMETHOD(miibus_writereg, al_miibus_writereg), DEVMETHOD(miibus_statchg, al_miibus_statchg), DEVMETHOD(miibus_linkchg, al_miibus_linkchg), - { 0, 0 } + DEVMETHOD_END }; static driver_t al_driver = { diff --git a/sys/dev/alpm/alpm.c b/sys/dev/alpm/alpm.c index d7c3d3657d3b..2bf74c276a5f 100644 --- a/sys/dev/alpm/alpm.c +++ b/sys/dev/alpm/alpm.c @@ -642,7 +642,7 @@ static device_method_t alpm_methods[] = { DEVMETHOD(smbus_readw, alpm_readw), DEVMETHOD(smbus_bwrite, alpm_bwrite), DEVMETHOD(smbus_bread, alpm_bread), - { 0, 0 } + DEVMETHOD_END }; static driver_t alpm_driver = { diff --git a/sys/dev/amdpm/amdpm.c b/sys/dev/amdpm/amdpm.c index d744c0aa5d4b..f93cc5b2eaa7 100644 --- a/sys/dev/amdpm/amdpm.c +++ b/sys/dev/amdpm/amdpm.c @@ -648,7 +648,7 @@ static device_method_t amdpm_methods[] = { DEVMETHOD(smbus_readw, amdpm_readw), DEVMETHOD(smbus_bwrite, amdpm_bwrite), DEVMETHOD(smbus_bread, amdpm_bread), - { 0, 0 } + DEVMETHOD_END }; static driver_t amdpm_driver = { diff --git a/sys/dev/amdsmb/amdsmb.c b/sys/dev/amdsmb/amdsmb.c index 3d2e7a5e0c19..65992dc34b02 100644 --- a/sys/dev/amdsmb/amdsmb.c +++ b/sys/dev/amdsmb/amdsmb.c @@ -560,7 +560,7 @@ static device_method_t amdsmb_methods[] = { DEVMETHOD(smbus_readw, amdsmb_readw), DEVMETHOD(smbus_bwrite, amdsmb_bwrite), DEVMETHOD(smbus_bread, amdsmb_bread), - { 0, 0 } + DEVMETHOD_END }; static driver_t amdsmb_driver = { diff --git a/sys/dev/amdsmu/amdsmu.c b/sys/dev/amdsmu/amdsmu.c index 416f875c6176..7b97888887c5 100644 --- a/sys/dev/amdsmu/amdsmu.c +++ b/sys/dev/amdsmu/amdsmu.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2025 The FreeBSD Foundation + * Copyright (c) 2025-2026 The FreeBSD Foundation * * This software was developed by Aymeric Wibo <obiwac@freebsd.org> * under sponsorship from the FreeBSD Foundation. @@ -14,6 +14,13 @@ #include <sys/rman.h> #include <sys/sysctl.h> +#include "opt_acpi.h" + +#if defined(DEV_ACPI) +#include <contrib/dev/acpica/include/acpi.h> +#include <dev/acpica/acpivar.h> +#endif + #include <dev/pci/pcivar.h> #include <dev/amdsmu/amdsmu.h> @@ -51,9 +58,12 @@ amdsmu_identify(driver_t *driver, device_t parent) static int amdsmu_probe(device_t dev) { + struct amdsmu_softc *sc; + if (resource_disabled("amdsmu", 0)) return (ENXIO); - if (!amdsmu_match(device_get_parent(dev), NULL)) + sc = device_get_softc(dev); + if (!amdsmu_match(device_get_parent(dev), &sc->product)) return (ENXIO); device_set_descf(dev, "AMD System Management Unit"); @@ -147,28 +157,11 @@ static int amdsmu_get_ip_blocks(device_t dev) { struct amdsmu_softc *sc = device_get_softc(dev); - const uint16_t deviceid = pci_get_device(dev); int err; struct amdsmu_metrics *m = &sc->metrics; bool active; char sysctl_descr[32]; - /* Get IP block count. */ - switch (deviceid) { - case PCI_DEVICEID_AMD_REMBRANDT_ROOT: - sc->ip_block_count = 12; - break; - case PCI_DEVICEID_AMD_PHOENIX_ROOT: - sc->ip_block_count = 21; - break; - /* TODO How many IP blocks does Strix Point (and the others) have? */ - case PCI_DEVICEID_AMD_STRIX_POINT_ROOT: - default: - sc->ip_block_count = nitems(amdsmu_ip_blocks_names); - } - KASSERT(sc->ip_block_count <= nitems(amdsmu_ip_blocks_names), - ("too many IP blocks for array")); - /* Get and print out IP blocks. */ err = amdsmu_cmd(dev, SMU_MSG_GET_SUP_CONSTRAINTS, 0, &sc->active_ip_blocks); @@ -177,13 +170,13 @@ amdsmu_get_ip_blocks(device_t dev) return (err); } device_printf(dev, "Active IP blocks: "); - for (size_t i = 0; i < sc->ip_block_count; i++) { + for (size_t i = 0; i < sc->product->ip_block_count; i++) { active = (sc->active_ip_blocks & (1 << i)) != 0; sc->ip_blocks_active[i] = active; if (!active) continue; printf("%s%s", amdsmu_ip_blocks_names[i], - i + 1 < sc->ip_block_count ? " " : "\n"); + i + 1 < sc->product->ip_block_count ? " " : "\n"); } /* Create a sysctl node for IP blocks. */ @@ -196,7 +189,7 @@ amdsmu_get_ip_blocks(device_t dev) } /* Create a sysctl node for each IP block. */ - for (size_t i = 0; i < sc->ip_block_count; i++) { + for (size_t i = 0; i < sc->product->ip_block_count; i++) { /* Create the sysctl node itself for the IP block. */ snprintf(sysctl_descr, sizeof sysctl_descr, "Metrics about the %s AMD IP block", @@ -286,7 +279,32 @@ amdsmu_fetch_idlemask(device_t dev) { struct amdsmu_softc *sc = device_get_softc(dev); - sc->idlemask = amdsmu_read4(sc, SMU_REG_IDLEMASK); + sc->idlemask = amdsmu_read4(sc, sc->product->idlemask_reg); +} + +static void +amdsmu_suspend(device_t dev, enum power_stype stype) +{ + if (stype != POWER_STYPE_SUSPEND_TO_IDLE) + return; + /* + * XXX It seems that Cezanne needs a special workaround here for + * firmware versions < 64.53. See amd_pmc_verify_czn_rtc() in Linux. + */ + if (amdsmu_cmd(dev, SMU_MSG_SLEEP_HINT, true, NULL) != 0) + device_printf(dev, "failed to hint to SMU to enter sleep"); +} + +static void +amdsmu_resume(device_t dev, enum power_stype stype) +{ + if (stype != POWER_STYPE_SUSPEND_TO_IDLE) + return; + if (amdsmu_cmd(dev, SMU_MSG_SLEEP_HINT, false, NULL) != 0) + device_printf(dev, "failed to hint to SMU to exit sleep"); + /* Update metrics after resume. */ + amdsmu_dump_metrics(dev); + amdsmu_fetch_idlemask(dev); } static int @@ -422,6 +440,19 @@ amdsmu_attach(device_t dev) "value is not documented - only used to help AMD internally debug " "issues"); +#if defined(DEV_ACPI) + /* + * Register post device suspend/pre device resume eventhandlers. We use + * a lower priority for the suspend event as we want this to be called + * after the SPMC suspend hook, and a higher priority for the resume + * event as we want this to be called before the SPMC hook. + */ + sc->eh_suspend = EVENTHANDLER_REGISTER(acpi_post_dev_suspend, + amdsmu_suspend, dev, -10); + sc->eh_resume = EVENTHANDLER_REGISTER(acpi_pre_dev_resume, + amdsmu_resume, dev, 10); +#endif + return (0); err_dump: bus_space_unmap(sc->bus_tag, sc->reg_space, SMU_MEM_SIZE); @@ -438,6 +469,11 @@ amdsmu_detach(device_t dev) struct amdsmu_softc *sc = device_get_softc(dev); int rid = 0; +#if defined(DEV_ACPI) + EVENTHANDLER_DEREGISTER(acpi_post_dev_suspend, sc->eh_suspend); + EVENTHANDLER_DEREGISTER(acpi_pre_dev_resume, sc->eh_resume); +#endif + bus_space_unmap(sc->bus_tag, sc->smu_space, SMU_MEM_SIZE); bus_space_unmap(sc->bus_tag, sc->reg_space, SMU_MEM_SIZE); diff --git a/sys/dev/amdsmu/amdsmu.h b/sys/dev/amdsmu/amdsmu.h index 025887f7fe5a..4286d515ae77 100644 --- a/sys/dev/amdsmu/amdsmu.h +++ b/sys/dev/amdsmu/amdsmu.h @@ -6,11 +6,13 @@ * This software was developed by Aymeric Wibo <obiwac@freebsd.org> * under sponsorship from the FreeBSD Foundation. */ + #ifndef _AMDSMU_H_ #define _AMDSMU_H_ #include <sys/param.h> #include <sys/bus.h> +#include <sys/eventhandler.h> #include <sys/kernel.h> #include <machine/bus.h> #include <x86/cputypes.h> @@ -23,10 +25,20 @@ static const struct amdsmu_product { uint16_t amdsmu_vendorid; uint16_t amdsmu_deviceid; + int16_t idlemask_reg; + size_t ip_block_count; } amdsmu_products[] = { - { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_REMBRANDT_ROOT }, - { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_PHOENIX_ROOT }, - { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_STRIX_POINT_ROOT }, + { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_CEZANNE_ROOT, + SMU_REG_IDLEMASK_CEZANNE, 12 }, + { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_REMBRANDT_ROOT, + SMU_REG_IDLEMASK_PHOENIX, 12 }, + { CPU_VENDOR_AMD, PCI_DEVICEID_AMD_PHOENIX_ROOT, + SMU_REG_IDLEMASK_PHOENIX, 21 }, + /* + * XXX Strix Point (PCI_DEVICEID_AMD_STRIX_POINT_ROOT) doesn't support + * S0i3 and thus doesn't have an idlemask. Since our driver doesn't + * yet understand this, don't attach to Strix Point for the time being. + */ }; static const char *const amdsmu_ip_blocks_names[] = { @@ -57,9 +69,14 @@ static const char *const amdsmu_ip_blocks_names[] = { CTASSERT(nitems(amdsmu_ip_blocks_names) <= 32); struct amdsmu_softc { + const struct amdsmu_product *product; + struct sysctl_ctx_list *sysctlctx; struct sysctl_oid *sysctlnode; + struct eventhandler_entry *eh_suspend; + struct eventhandler_entry *eh_resume; + struct resource *res; bus_space_tag_t bus_tag; @@ -71,9 +88,10 @@ struct amdsmu_softc { uint32_t active_ip_blocks; struct sysctl_oid *ip_blocks_sysctlnode; - size_t ip_block_count; - struct sysctl_oid *ip_block_sysctlnodes[nitems(amdsmu_ip_blocks_names)]; - bool ip_blocks_active[nitems(amdsmu_ip_blocks_names)]; + struct sysctl_oid *ip_block_sysctlnodes[ + nitems(amdsmu_ip_blocks_names)]; + bool ip_blocks_active[ + nitems(amdsmu_ip_blocks_names)]; bus_space_handle_t metrics_space; struct amdsmu_metrics metrics; diff --git a/sys/dev/amdsmu/amdsmu_reg.h b/sys/dev/amdsmu/amdsmu_reg.h index e685b34e6883..6afbcf006535 100644 --- a/sys/dev/amdsmu/amdsmu_reg.h +++ b/sys/dev/amdsmu/amdsmu_reg.h @@ -16,6 +16,7 @@ * out? Also, there are way more of these. I couldn't find a centralized place * which lists them though. */ +#define PCI_DEVICEID_AMD_CEZANNE_ROOT 0x1630 #define PCI_DEVICEID_AMD_REMBRANDT_ROOT 0x14B5 #define PCI_DEVICEID_AMD_PHOENIX_ROOT 0x14E8 #define PCI_DEVICEID_AMD_STRIX_POINT_ROOT 0x14A4 @@ -32,7 +33,9 @@ #define SMU_REG_MESSAGE 0x538 #define SMU_REG_RESPONSE 0x980 #define SMU_REG_ARGUMENT 0x9BC -#define SMU_REG_IDLEMASK 0xD14 + +#define SMU_REG_IDLEMASK_CEZANNE 0x94 +#define SMU_REG_IDLEMASK_PHOENIX 0xD14 enum amdsmu_res { SMU_RES_WAIT = 0x00, @@ -45,6 +48,7 @@ enum amdsmu_res { enum amdsmu_msg { SMU_MSG_GETSMUVERSION = 0x02, + SMU_MSG_SLEEP_HINT = 0x03, SMU_MSG_LOG_GETDRAM_ADDR_HI = 0x04, SMU_MSG_LOG_GETDRAM_ADDR_LO = 0x05, SMU_MSG_LOG_START = 0x06, diff --git a/sys/dev/aq/aq_common.h b/sys/dev/aq/aq_common.h index af59ecf7af1e..f31567480ec0 100644 --- a/sys/dev/aq/aq_common.h +++ b/sys/dev/aq/aq_common.h @@ -67,5 +67,4 @@ do { \ #define AQ_VER "0.0.5" -#endif //_AQ_COMMON_H_ - +#endif // _AQ_COMMON_H_ diff --git a/sys/dev/aq/aq_dbg.c b/sys/dev/aq/aq_dbg.c index 495991fafbdc..bed29b3d0755 100644 --- a/sys/dev/aq/aq_dbg.c +++ b/sys/dev/aq/aq_dbg.c @@ -56,7 +56,8 @@ const uint32_t dbg_categories_ = dbg_init | dbg_config | dbg_fw; #define __field(TYPE, VAR) TYPE VAR; void -trace_aq_tx_descr(int ring_idx, unsigned int pointer, volatile uint64_t descr[2]) +trace_aq_tx_descr(int ring_idx, unsigned int pointer, + volatile uint64_t descr[2]) { #if AQ_CFG_DEBUG_LVL > 2 struct __entry{ @@ -211,7 +212,8 @@ DumpHex(const void* data, size_t size) { for (i = 0; i < size; ++i) { sprintf(buf, "%02X ", ((const unsigned char*)data)[i]); strcat(line, buf); - if (((const unsigned char*)data)[i] >= ' ' && ((const unsigned char*)data)[i] <= '~') { + if (((const unsigned char*)data)[i] >= ' ' && + ((const unsigned char*)data)[i] <= '~') { ascii[i % 16] = ((const unsigned char*)data)[i]; } else { ascii[i % 16] = '.'; diff --git a/sys/dev/aq/aq_device.h b/sys/dev/aq/aq_device.h index 2b170f710840..64edbd138b3a 100644 --- a/sys/dev/aq/aq_device.h +++ b/sys/dev/aq/aq_device.h @@ -147,4 +147,4 @@ void aq_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr); int aq_mediachange(struct ifnet *ifp); void aq_if_update_admin_status(if_ctx_t ctx); -#endif +#endif // _AQ_DEVICE_H_ diff --git a/sys/dev/aq/aq_fw.c b/sys/dev/aq/aq_fw.c index fac720ba2327..3ab5909882e1 100644 --- a/sys/dev/aq/aq_fw.c +++ b/sys/dev/aq/aq_fw.c @@ -62,6 +62,7 @@ typedef enum aq_fw_bootloader_mode } aq_fw_bootloader_mode; #define AQ_CFG_HOST_BOOT_DISABLE 0 + // Timeouts #define RBL_TIMEOUT_MS 10000 #define MAC_FW_START_TIMEOUT_MS 10000 @@ -215,12 +216,14 @@ mac_soft_reset_flb_(struct aq_hw* hw) int k; reg_global_ctl2_set(hw, 0x40e1); - // Let Felicity hardware to complete SMBUS transaction before Global software reset. + // Let Felicity hardware complete SMBUS transaction before Global + // software reset. msec_delay(50); /* - * If SPI burst transaction was interrupted(before running the script), global software - * reset may not clear SPI interface. Clean it up manually before global reset. + * If SPI burst transaction was interrupted(before running the script), + * global software reset may not clear SPI interface. Clean it up + * manually before global reset. */ reg_glb_nvr_provisioning2_set(hw, 0xa0); reg_glb_nvr_interface1_set(hw, 0x9f); @@ -236,8 +239,8 @@ mac_soft_reset_flb_(struct aq_hw* hw) reg_glb_general_provisioning9_set(hw, 1); /* - * For the case SPI burst transaction was interrupted (by MCP reset above), - * wait until it is completed by hardware. + * For the case SPI burst transaction was interrupted (by MCP reset + * above), wait until it is completed by hardware. */ msec_delay(50); // Sleep for 10 ms. @@ -263,7 +266,8 @@ mac_soft_reset_flb_(struct aq_hw* hw) trace(dbg_init, "FLB> MAC kickstart done, %d ms", k); /* FW reset */ reg_global_ctl2_set(hw, 0x80e0); - // Let Felicity hardware complete SMBUS transaction before Global software reset. + // Let Felicity hardware complete SMBUS transaction before + // Global software reset. msec_delay(50); } reg_glb_cpu_sem_set(hw, 1, 0); diff --git a/sys/dev/aq/aq_fw1x.c b/sys/dev/aq/aq_fw1x.c index 10328fdbb01c..5a409eef15f4 100644 --- a/sys/dev/aq/aq_fw1x.c +++ b/sys/dev/aq/aq_fw1x.c @@ -171,7 +171,8 @@ fw1x_reset(struct aq_hw* hal) const int retryCount = 1000; for (int i = 0; i < retryCount; ++i) { - // Read the beginning of Statistics structure to capture the Transaction ID. + // Read the beginning of Statistics structure to capture the + // Transaction ID. aq_hw_fw_downld_dwords(hal, hal->mbox_addr, (uint32_t*)&mbox, (uint32_t)((char*)&mbox.stats - (char*)&mbox) / sizeof(uint32_t)); @@ -185,7 +186,6 @@ fw1x_reset(struct aq_hw* hal) * Compare transaction ID to initial value. * If it's different means f/w is alive. We're done. */ - return (EOK); } @@ -321,4 +321,3 @@ struct aq_firmware_ops aq_fw1x_ops = .get_mac_addr = fw1x_get_mac_addr, .get_stats = fw1x_get_stats, }; - diff --git a/sys/dev/aq/aq_fw2x.c b/sys/dev/aq/aq_fw2x.c index 7a39a0ddc7e6..004121242ac1 100644 --- a/sys/dev/aq/aq_fw2x.c +++ b/sys/dev/aq/aq_fw2x.c @@ -193,7 +193,6 @@ typedef struct fw2x_mailbox // struct fwHostInterface #define FW2X_LED_DEFAULT 0x0U // Firmware v2-3.x specific functions. -//@{ int fw2x_reset(struct aq_hw* hw); int fw2x_set_mode(struct aq_hw* hw, enum aq_hw_fw_mpi_state_e mode, @@ -203,8 +202,6 @@ int fw2x_get_mode(struct aq_hw* hw, enum aq_hw_fw_mpi_state_e* mode, int fw2x_get_mac_addr(struct aq_hw* hw, uint8_t* mac); int fw2x_get_stats(struct aq_hw* hw, struct aq_hw_stats_s* stats); -//@} - static uint64_t @@ -474,7 +471,7 @@ fw2x_get_stats(struct aq_hw* hw, struct aq_hw_stats_s* stats) return (-ENOTSUP); } - // Say to F/W to update the statistics + // Tell F/W to update the statistics. if (!toggle_mpi_ctrl_and_wait_(hw, FW2X_CAP_STATISTICS, 1, 25)) { trace_error(dbg_fw, "fw2x> statistics update timeout"); AQ_DBG_EXIT(-ETIME); diff --git a/sys/dev/aq/aq_hw.c b/sys/dev/aq/aq_hw.c index fe48e255254a..f73805a939cd 100644 --- a/sys/dev/aq/aq_hw.c +++ b/sys/dev/aq/aq_hw.c @@ -796,9 +796,11 @@ hw_atl_b0_hw_vlan_promisc_set(struct aq_hw_s *self, bool promisc) void -aq_hw_set_promisc(struct aq_hw_s *self, bool l2_promisc, bool vlan_promisc, bool mc_promisc) +aq_hw_set_promisc(struct aq_hw_s *self, bool l2_promisc, bool vlan_promisc, + bool mc_promisc) { - AQ_DBG_ENTERA("promisc %d, vlan_promisc %d, allmulti %d", l2_promisc, vlan_promisc, mc_promisc); + AQ_DBG_ENTERA("promisc %d, vlan_promisc %d, allmulti %d", l2_promisc, + vlan_promisc, mc_promisc); rpfl2promiscuous_mode_en_set(self, l2_promisc); @@ -811,7 +813,8 @@ aq_hw_set_promisc(struct aq_hw_s *self, bool l2_promisc, bool vlan_promisc, bool } int -aq_hw_rss_hash_set(struct aq_hw_s *self, uint8_t rss_key[HW_ATL_RSS_HASHKEY_SIZE]) +aq_hw_rss_hash_set(struct aq_hw_s *self, + uint8_t rss_key[HW_ATL_RSS_HASHKEY_SIZE]) { uint32_t rss_key_dw[HW_ATL_RSS_HASHKEY_SIZE / 4]; uint32_t addr = 0U; @@ -841,7 +844,8 @@ err_exit: } int -aq_hw_rss_hash_get(struct aq_hw_s *self, uint8_t rss_key[HW_ATL_RSS_HASHKEY_SIZE]) +aq_hw_rss_hash_get(struct aq_hw_s *self, + uint8_t rss_key[HW_ATL_RSS_HASHKEY_SIZE]) { uint32_t rss_key_dw[HW_ATL_RSS_HASHKEY_SIZE / 4]; uint32_t addr = 0U; @@ -863,7 +867,8 @@ aq_hw_rss_hash_get(struct aq_hw_s *self, uint8_t rss_key[HW_ATL_RSS_HASHKEY_SIZE } int -aq_hw_rss_set(struct aq_hw_s *self, uint8_t rss_table[HW_ATL_RSS_INDIRECTION_TABLE_MAX]) +aq_hw_rss_set(struct aq_hw_s *self, + uint8_t rss_table[HW_ATL_RSS_INDIRECTION_TABLE_MAX]) { uint16_t bitary[(HW_ATL_RSS_INDIRECTION_TABLE_MAX * 3 / 16U)]; diff --git a/sys/dev/aq/aq_hw.h b/sys/dev/aq/aq_hw.h index fb07f7c8b838..a4d4dbb3a512 100644 --- a/sys/dev/aq/aq_hw.h +++ b/sys/dev/aq/aq_hw.h @@ -356,5 +356,4 @@ int aq_hw_rss_hash_get(struct aq_hw_s *self, uint8_t rss_key[HW_ATL_RSS_HASHKEY_ int aq_hw_rss_set(struct aq_hw_s *self, uint8_t rss_table[HW_ATL_RSS_INDIRECTION_TABLE_MAX]); int aq_hw_udp_rss_enable(struct aq_hw_s *self, bool enable); -#endif //_AQ_HW_H_ - +#endif // _AQ_HW_H_ diff --git a/sys/dev/aq/aq_hw_llh.c b/sys/dev/aq/aq_hw_llh.c index 87384ad46618..43f966becf50 100644 --- a/sys/dev/aq/aq_hw_llh.c +++ b/sys/dev/aq/aq_hw_llh.c @@ -89,7 +89,8 @@ reg_global_ctl2_get(struct aq_hw* hw) } void -reg_glb_daisy_chain_status1_set(struct aq_hw* hw, uint32_t glb_daisy_chain_status1) +reg_glb_daisy_chain_status1_set(struct aq_hw* hw, + uint32_t glb_daisy_chain_status1) { AQ_WRITE_REG(hw, glb_daisy_chain_status1_adr, glb_daisy_chain_status1); } @@ -459,7 +460,8 @@ itr_mif_int_map_en_get(struct aq_hw *aq_hw, uint32_t mif) } void -itr_mif_int_map_set(struct aq_hw *aq_hw, uint32_t mifInterruptMapping, uint32_t mif) +itr_mif_int_map_set(struct aq_hw *aq_hw, uint32_t mifInterruptMapping, + uint32_t mif) { AQ_WRITE_REG_BIT(aq_hw, itrImrMifM_ADR(mif), itrImrMifM_MSK(mif), itrImrMifM_SHIFT(mif), mifInterruptMapping); @@ -516,8 +518,8 @@ rdm_rx_dca_mode_set(struct aq_hw *aq_hw, uint32_t rx_dca_mode) } void -rdm_rx_desc_data_buff_size_set(struct aq_hw *aq_hw, uint32_t rx_desc_data_buff_size, - uint32_t descriptor) +rdm_rx_desc_data_buff_size_set(struct aq_hw *aq_hw, + uint32_t rx_desc_data_buff_size, uint32_t descriptor) { AQ_WRITE_REG_BIT(aq_hw, rdm_descddata_size_adr(descriptor), rdm_descddata_size_msk, rdm_descddata_size_shift, @@ -525,14 +527,16 @@ rdm_rx_desc_data_buff_size_set(struct aq_hw *aq_hw, uint32_t rx_desc_data_buff_s } void -rdm_rx_desc_dca_en_set(struct aq_hw *aq_hw, uint32_t rx_desc_dca_en, uint32_t dca) +rdm_rx_desc_dca_en_set(struct aq_hw *aq_hw, uint32_t rx_desc_dca_en, + uint32_t dca) { AQ_WRITE_REG_BIT(aq_hw, rdm_dcaddesc_en_adr(dca), rdm_dcaddesc_en_msk, rdm_dcaddesc_en_shift, rx_desc_dca_en); } void -rdm_rx_desc_en_set(struct aq_hw *aq_hw, uint32_t rx_desc_en, uint32_t descriptor) +rdm_rx_desc_en_set(struct aq_hw *aq_hw, uint32_t rx_desc_en, + uint32_t descriptor) { AQ_WRITE_REG_BIT(aq_hw, rdm_descden_adr(descriptor), rdm_descden_msk, rdm_descden_shift, rx_desc_en); @@ -564,14 +568,16 @@ rdm_rx_desc_head_ptr_get(struct aq_hw *aq_hw, uint32_t descriptor) } void -rdm_rx_desc_len_set(struct aq_hw *aq_hw, uint32_t rx_desc_len, uint32_t descriptor) +rdm_rx_desc_len_set(struct aq_hw *aq_hw, uint32_t rx_desc_len, + uint32_t descriptor) { AQ_WRITE_REG_BIT(aq_hw, rdm_descdlen_adr(descriptor), rdm_descdlen_msk, rdm_descdlen_shift, rx_desc_len); } void -rdm_rx_desc_res_set(struct aq_hw *aq_hw, uint32_t rx_desc_res, uint32_t descriptor) +rdm_rx_desc_res_set(struct aq_hw *aq_hw, uint32_t rx_desc_res, + uint32_t descriptor) { AQ_WRITE_REG_BIT(aq_hw, rdm_descdreset_adr(descriptor), rdm_descdreset_msk, rdm_descdreset_shift, rx_desc_res); @@ -587,7 +593,8 @@ rdm_rx_desc_wr_wb_irq_en_set(struct aq_hw *aq_hw, } void -rdm_rx_head_dca_en_set(struct aq_hw *aq_hw, uint32_t rx_head_dca_en, uint32_t dca) +rdm_rx_head_dca_en_set(struct aq_hw *aq_hw, uint32_t rx_head_dca_en, + uint32_t dca) { AQ_WRITE_REG_BIT(aq_hw, rdm_dcadhdr_en_adr(dca), rdm_dcadhdr_en_msk, rdm_dcadhdr_en_shift, rx_head_dca_en); @@ -960,7 +967,8 @@ rpf_rss_redir_tbl_addr_set(struct aq_hw *aq_hw, uint32_t rss_redir_tbl_addr) } void -rpf_rss_redir_tbl_wr_data_set(struct aq_hw *aq_hw, uint32_t rss_redir_tbl_wr_data) +rpf_rss_redir_tbl_wr_data_set(struct aq_hw *aq_hw, + uint32_t rss_redir_tbl_wr_data) { AQ_WRITE_REG_BIT(aq_hw, rpf_rss_redir_wr_data_adr, rpf_rss_redir_wr_data_msk, rpf_rss_redir_wr_data_shift, @@ -1010,7 +1018,8 @@ hw_atl_rpf_vlan_outer_etht_set(struct aq_hw_s *aq_hw, uint32_t vlan_outer_etht) } void -hw_atl_rpf_vlan_prom_mode_en_set(struct aq_hw_s *aq_hw, uint32_t vlan_prom_mode_en) +hw_atl_rpf_vlan_prom_mode_en_set(struct aq_hw_s *aq_hw, + uint32_t vlan_prom_mode_en) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_VL_PROMIS_MODE_ADR, HW_ATL_RPF_VL_PROMIS_MODE_MSK, @@ -1029,7 +1038,8 @@ hw_atl_rpf_vlan_accept_untagged_packets_set(struct aq_hw_s *aq_hw, } void -hw_atl_rpf_vlan_untagged_act_set(struct aq_hw_s *aq_hw, uint32_t vlan_untagged_act) +hw_atl_rpf_vlan_untagged_act_set(struct aq_hw_s *aq_hw, + uint32_t vlan_untagged_act) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_VL_UNTAGGED_ACT_ADR, HW_ATL_RPF_VL_UNTAGGED_ACT_MSK, @@ -1038,7 +1048,8 @@ hw_atl_rpf_vlan_untagged_act_set(struct aq_hw_s *aq_hw, uint32_t vlan_untagged_a } void -hw_atl_rpf_vlan_flr_en_set(struct aq_hw_s *aq_hw, uint32_t vlan_flr_en, uint32_t filter) +hw_atl_rpf_vlan_flr_en_set(struct aq_hw_s *aq_hw, uint32_t vlan_flr_en, + uint32_t filter) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_VL_EN_F_ADR(filter), HW_ATL_RPF_VL_EN_F_MSK, @@ -1047,7 +1058,8 @@ hw_atl_rpf_vlan_flr_en_set(struct aq_hw_s *aq_hw, uint32_t vlan_flr_en, uint32_t } void -hw_atl_rpf_vlan_flr_act_set(struct aq_hw_s *aq_hw, uint32_t vlan_flr_act, uint32_t filter) +hw_atl_rpf_vlan_flr_act_set(struct aq_hw_s *aq_hw, uint32_t vlan_flr_act, + uint32_t filter) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_VL_ACT_F_ADR(filter), HW_ATL_RPF_VL_ACT_F_MSK, @@ -1056,7 +1068,8 @@ hw_atl_rpf_vlan_flr_act_set(struct aq_hw_s *aq_hw, uint32_t vlan_flr_act, uint32 } void -hw_atl_rpf_vlan_id_flr_set(struct aq_hw_s *aq_hw, uint32_t vlan_id_flr, uint32_t filter) +hw_atl_rpf_vlan_id_flr_set(struct aq_hw_s *aq_hw, uint32_t vlan_id_flr, + uint32_t filter) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_VL_ID_F_ADR(filter), HW_ATL_RPF_VL_ID_F_MSK, @@ -1075,7 +1088,8 @@ hw_atl_rpf_vlan_rxq_en_flr_set(struct aq_hw_s *aq_hw, uint32_t vlan_rxq_en, } void -hw_atl_rpf_vlan_rxq_flr_set(struct aq_hw_s *aq_hw, uint32_t vlan_rxq, uint32_t filter) +hw_atl_rpf_vlan_rxq_flr_set(struct aq_hw_s *aq_hw, uint32_t vlan_rxq, + uint32_t filter) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_VL_RXQ_F_ADR(filter), HW_ATL_RPF_VL_RXQ_F_MSK, @@ -1084,7 +1098,8 @@ hw_atl_rpf_vlan_rxq_flr_set(struct aq_hw_s *aq_hw, uint32_t vlan_rxq, uint32_t f }; void -hw_atl_rpf_etht_flr_en_set(struct aq_hw_s *aq_hw, uint32_t etht_flr_en, uint32_t filter) +hw_atl_rpf_etht_flr_en_set(struct aq_hw_s *aq_hw, uint32_t etht_flr_en, + uint32_t filter) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_ET_ENF_ADR(filter), HW_ATL_RPF_ET_ENF_MSK, @@ -1101,8 +1116,8 @@ hw_atl_rpf_etht_user_priority_en_set(struct aq_hw_s *aq_hw, } void -hw_atl_rpf_etht_rx_queue_en_set(struct aq_hw_s *aq_hw, uint32_t etht_rx_queue_en, - uint32_t filter) +hw_atl_rpf_etht_rx_queue_en_set(struct aq_hw_s *aq_hw, + uint32_t etht_rx_queue_en, uint32_t filter) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_ET_RXQFEN_ADR(filter), HW_ATL_RPF_ET_RXQFEN_MSK, @@ -1111,8 +1126,8 @@ hw_atl_rpf_etht_rx_queue_en_set(struct aq_hw_s *aq_hw, uint32_t etht_rx_queue_en } void -hw_atl_rpf_etht_user_priority_set(struct aq_hw_s *aq_hw, uint32_t etht_user_priority, - uint32_t filter) +hw_atl_rpf_etht_user_priority_set(struct aq_hw_s *aq_hw, + uint32_t etht_user_priority, uint32_t filter) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_ET_UPF_ADR(filter), HW_ATL_RPF_ET_UPF_MSK, @@ -1148,7 +1163,8 @@ hw_atl_rpf_etht_flr_act_set(struct aq_hw_s *aq_hw, uint32_t etht_flr_act, } void -hw_atl_rpf_etht_flr_set(struct aq_hw_s *aq_hw, uint32_t etht_flr, uint32_t filter) +hw_atl_rpf_etht_flr_set(struct aq_hw_s *aq_hw, uint32_t etht_flr, + uint32_t filter) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_ET_VALF_ADR(filter), HW_ATL_RPF_ET_VALF_MSK, @@ -1220,7 +1236,8 @@ hw_atl_rpf_l3_arpf_en_set(struct aq_hw_s *aq_hw, uint32_t val, uint32_t filter) } void -hw_atl_rpf_l3_l4_rxqf_en_set(struct aq_hw_s *aq_hw, uint32_t val, uint32_t filter) +hw_atl_rpf_l3_l4_rxqf_en_set(struct aq_hw_s *aq_hw, uint32_t val, + uint32_t filter) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_L3_L4_RXQF_EN_ADR(filter), HW_ATL_RPF_L3_L4_RXQF_EN_MSK, @@ -1228,7 +1245,8 @@ hw_atl_rpf_l3_l4_rxqf_en_set(struct aq_hw_s *aq_hw, uint32_t val, uint32_t filte } void -hw_atl_rpf_l3_l4_mng_rxqf_set(struct aq_hw_s *aq_hw, uint32_t val, uint32_t filter) +hw_atl_rpf_l3_l4_mng_rxqf_set(struct aq_hw_s *aq_hw, uint32_t val, + uint32_t filter) { aq_hw_write_reg_bit(aq_hw, HW_ATL_RPF_L3_L4_MNG_RXQF_ADR(filter), HW_ATL_RPF_L3_L4_MNG_RXQF_MSK, @@ -1321,7 +1339,8 @@ rpf_vlan_flr_en_set(struct aq_hw *aq_hw, uint32_t vlan_flr_en, uint32_t filter) } void -rpf_vlan_flr_act_set(struct aq_hw *aq_hw, uint32_t vlan_flr_act, uint32_t filter) +rpf_vlan_flr_act_set(struct aq_hw *aq_hw, uint32_t vlan_flr_act, + uint32_t filter) { AQ_WRITE_REG_BIT(aq_hw, rpf_vl_act_f_adr(filter), rpf_vl_act_f_msk, rpf_vl_act_f_shift, vlan_flr_act); @@ -1366,21 +1385,24 @@ rpf_etht_user_priority_set(struct aq_hw *aq_hw, uint32_t etht_user_priority, } void -rpf_etht_rx_queue_set(struct aq_hw *aq_hw, uint32_t etht_rx_queue, uint32_t filter) +rpf_etht_rx_queue_set(struct aq_hw *aq_hw, uint32_t etht_rx_queue, + uint32_t filter) { AQ_WRITE_REG_BIT(aq_hw, rpf_et_rxqf_adr(filter), rpf_et_rxqf_msk, rpf_et_rxqf_shift, etht_rx_queue); } void -rpf_etht_mgt_queue_set(struct aq_hw *aq_hw, uint32_t etht_mgt_queue, uint32_t filter) +rpf_etht_mgt_queue_set(struct aq_hw *aq_hw, uint32_t etht_mgt_queue, + uint32_t filter) { AQ_WRITE_REG_BIT(aq_hw, rpf_et_mng_rxqf_adr(filter), rpf_et_mng_rxqf_msk, rpf_et_mng_rxqf_shift, etht_mgt_queue); } void -rpf_etht_flr_act_set(struct aq_hw *aq_hw, uint32_t etht_flr_act, uint32_t filter) +rpf_etht_flr_act_set(struct aq_hw *aq_hw, uint32_t etht_flr_act, + uint32_t filter) { AQ_WRITE_REG_BIT(aq_hw, rpf_et_actf_adr(filter), rpf_et_actf_msk, rpf_et_actf_shift, etht_flr_act); @@ -1565,14 +1587,16 @@ tdm_tx_dca_mode_set(struct aq_hw *aq_hw, uint32_t tx_dca_mode) } void -tdm_tx_desc_dca_en_set(struct aq_hw *aq_hw, uint32_t tx_desc_dca_en, uint32_t dca) +tdm_tx_desc_dca_en_set(struct aq_hw *aq_hw, uint32_t tx_desc_dca_en, + uint32_t dca) { AQ_WRITE_REG_BIT(aq_hw, tdm_dcaddesc_en_adr(dca), tdm_dcaddesc_en_msk, tdm_dcaddesc_en_shift, tx_desc_dca_en); } void -tdm_tx_desc_en_set(struct aq_hw *aq_hw, uint32_t tx_desc_en, uint32_t descriptor) +tdm_tx_desc_en_set(struct aq_hw *aq_hw, uint32_t tx_desc_en, + uint32_t descriptor) { AQ_WRITE_REG_BIT(aq_hw, tdm_descden_adr(descriptor), tdm_descden_msk, tdm_descden_shift, tx_desc_en); @@ -1586,7 +1610,8 @@ tdm_tx_desc_head_ptr_get(struct aq_hw *aq_hw, uint32_t descriptor) } void -tdm_tx_desc_len_set(struct aq_hw *aq_hw, uint32_t tx_desc_len, uint32_t descriptor) +tdm_tx_desc_len_set(struct aq_hw *aq_hw, uint32_t tx_desc_len, + uint32_t descriptor) { AQ_WRITE_REG_BIT(aq_hw, tdm_descdlen_adr(descriptor), tdm_descdlen_msk, tdm_descdlen_shift, tx_desc_len); @@ -1721,7 +1746,8 @@ tpo_ipv4header_crc_offload_en_set(struct aq_hw *aq_hw, } void -tpo_tcp_udp_crc_offload_en_set(struct aq_hw *aq_hw, uint32_t tcp_udp_crc_offload_en) +tpo_tcp_udp_crc_offload_en_set(struct aq_hw *aq_hw, + uint32_t tcp_udp_crc_offload_en) { AQ_WRITE_REG_BIT(aq_hw, tpol4chk_en_adr, tpol4chk_en_msk, tpol4chk_en_shift, tcp_udp_crc_offload_en); @@ -1876,7 +1902,8 @@ pci_pci_reg_res_dis_set(struct aq_hw *aq_hw, uint32_t pci_reg_res_dis) uint32_t reg_glb_cpu_scratch_scp_get(struct aq_hw *hw, uint32_t glb_cpu_scratch_scp_idx) { - return AQ_READ_REG(hw, glb_cpu_scratch_scp_adr(glb_cpu_scratch_scp_idx)); + return AQ_READ_REG(hw, + glb_cpu_scratch_scp_adr(glb_cpu_scratch_scp_idx)); } void reg_glb_cpu_scratch_scp_set(struct aq_hw *aq_hw, uint32_t glb_cpu_scratch_scp, @@ -1892,7 +1919,8 @@ reg_glb_cpu_no_reset_scratchpad_get(struct aq_hw *hw, uint32_t index) return AQ_READ_REG(hw, glb_cpu_no_reset_scratchpad_adr(index)); } void -reg_glb_cpu_no_reset_scratchpad_set(struct aq_hw* hw, uint32_t value, uint32_t index) +reg_glb_cpu_no_reset_scratchpad_set(struct aq_hw* hw, uint32_t value, + uint32_t index) { AQ_WRITE_REG(hw, glb_cpu_no_reset_scratchpad_adr(index), value); } diff --git a/sys/dev/aq/aq_media.c b/sys/dev/aq/aq_media.c index 9cdc0236bb60..f961f3bb5f0f 100644 --- a/sys/dev/aq/aq_media.c +++ b/sys/dev/aq/aq_media.c @@ -119,7 +119,9 @@ aq_mediachange(if_t ifp) AQ_DBG_ENTERA("media 0x%x", user_media); if (!(ifm->ifm_media & IFM_ETHER)) { - device_printf(aq_dev->dev, "%s(): aq_dev interface - bad media: 0x%X", __FUNCTION__, ifm->ifm_media); + device_printf(aq_dev->dev, + "%s(): aq_dev interface - bad media: 0x%X", __FUNCTION__, + ifm->ifm_media); return (0); // should never happen } diff --git a/sys/dev/aq/aq_ring.c b/sys/dev/aq/aq_ring.c index 40128cbb72b8..51014ae0a9d7 100644 --- a/sys/dev/aq/aq_ring.c +++ b/sys/dev/aq/aq_ring.c @@ -107,9 +107,11 @@ aq_ring_rx_init(struct aq_hw *hw, struct aq_ring *ring) rdm_rx_desc_len_set(hw, ring->rx_size / 8U, ring->index); - device_printf(ring->dev->dev, "ring %d: __PAGESIZE=%d MCLBYTES=%d hw->max_frame_size=%d\n", - ring->index, PAGE_SIZE, MCLBYTES, ring->rx_max_frame_size); - rdm_rx_desc_data_buff_size_set(hw, ring->rx_max_frame_size / 1024U, ring->index); + device_printf(ring->dev->dev, + "ring %d: __PAGESIZE=%d MCLBYTES=%d hw->max_frame_size=%d\n", + ring->index, PAGE_SIZE, MCLBYTES, ring->rx_max_frame_size); + rdm_rx_desc_data_buff_size_set(hw, ring->rx_max_frame_size / 1024U, + ring->index); rdm_rx_desc_head_buff_size_set(hw, 0U, ring->index); rdm_rx_desc_head_splitting_set(hw, 0U, ring->index); @@ -279,7 +281,8 @@ aq_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget) for (iter = 0, cnt = 0, i = idx; iter < ring->rx_size && cnt <= budget;) { - trace_aq_rx_descr(ring->index, i, (volatile uint64_t*)&rx_desc[i]); + trace_aq_rx_descr(ring->index, i, + (volatile uint64_t*)&rx_desc[i]); if (!rx_desc[i].wb.dd) break; @@ -309,8 +312,8 @@ aq_isc_rxd_available(void *arg, uint16_t rxqid, qidx_t idx, qidx_t budget) static void aq_rx_set_cso_flags(aq_rx_desc_t *rx_desc, if_rxd_info_t ri) { - if ((rx_desc->wb.pkt_type & 0x3) == 0) { //IPv4 - if (rx_desc->wb.rx_cntl & BIT(0)){ // IPv4 csum checked + if ((rx_desc->wb.pkt_type & 0x3) == 0) { // IPv4 + if (rx_desc->wb.rx_cntl & BIT(0)) { // IPv4 csum checked ri->iri_csum_flags |= CSUM_IP_CHECKED; if (!(rx_desc->wb.rx_stat & BIT(1))) ri->iri_csum_flags |= CSUM_IP_VALID; @@ -355,7 +358,8 @@ aq_isc_rxd_pkt_get(void *arg, if_rxd_info_t ri) do { rx_desc = (aq_rx_desc_t *) &ring->rx_descs[cidx]; - trace_aq_rx_descr(ring->index, cidx, (volatile uint64_t*)rx_desc); + trace_aq_rx_descr(ring->index, cidx, + (volatile uint64_t *)rx_desc); if ((rx_desc->wb.rx_stat & BIT(0)) != 0) { ring->stats.rx_err++; diff --git a/sys/dev/asmc/asmc.c b/sys/dev/asmc/asmc.c index 5d3b97a065c9..0a701e6fd663 100644 --- a/sys/dev/asmc/asmc.c +++ b/sys/dev/asmc/asmc.c @@ -51,12 +51,16 @@ #include <sys/rman.h> #include <machine/resource.h> +#include <netinet/in.h> #include <contrib/dev/acpica/include/acpi.h> #include <dev/acpica/acpivar.h> #include <dev/asmc/asmcvar.h> +#include <dev/backlight/backlight.h> +#include "backlight_if.h" + /* * Device interface. */ @@ -66,6 +70,15 @@ static int asmc_detach(device_t dev); static int asmc_resume(device_t dev); /* + * Backlight interface. + */ +static int asmc_backlight_update_status(device_t dev, + struct backlight_props *props); +static int asmc_backlight_get_status(device_t dev, + struct backlight_props *props); +static int asmc_backlight_get_info(device_t dev, struct backlight_info *info); + +/* * SMC functions. */ static int asmc_init(device_t dev); @@ -108,10 +121,27 @@ static int asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS); static int asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS); static int asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS); static int asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS); +static int asmc_wol_sysctl(SYSCTL_HANDLER_ARGS); + +static int asmc_key_getinfo(device_t, const char *, uint8_t *, char *); + +#ifdef ASMC_DEBUG +/* Raw key access */ +static int asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS); +static int asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS); +static int asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS); +static int asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS); +#endif + +/* Voltage/Current/Power/Light sensor support */ +static int asmc_sensor_read(device_t, const char *, int *); +static int asmc_sensor_sysctl(SYSCTL_HANDLER_ARGS); +static int asmc_detect_sensors(device_t); +static int asmc_key_dump_by_index(device_t, int, char *, char *, uint8_t *); struct asmc_model { - const char *smc_model; /* smbios.system.product env var. */ - const char *smc_desc; /* driver description */ + const char *smc_model; /* smbios.system.product env var. */ + const char *smc_desc; /* driver description */ /* Helper functions */ int (*smc_sms_x)(SYSCTL_HANDLER_ARGS); @@ -134,48 +164,68 @@ struct asmc_model { static const struct asmc_model *asmc_match(device_t dev); -#define ASMC_SMS_FUNCS asmc_mb_sysctl_sms_x, asmc_mb_sysctl_sms_y, \ - asmc_mb_sysctl_sms_z - -#define ASMC_SMS_FUNCS_DISABLED NULL,NULL,NULL - -#define ASMC_FAN_FUNCS asmc_mb_sysctl_fanid, asmc_mb_sysctl_fanspeed, asmc_mb_sysctl_fansafespeed, \ - asmc_mb_sysctl_fanminspeed, \ - asmc_mb_sysctl_fanmaxspeed, \ - asmc_mb_sysctl_fantargetspeed - -#define ASMC_FAN_FUNCS2 asmc_mb_sysctl_fanid, asmc_mb_sysctl_fanspeed, NULL, \ - asmc_mb_sysctl_fanminspeed, \ - asmc_mb_sysctl_fanmaxspeed, \ - asmc_mb_sysctl_fantargetspeed - -#define ASMC_LIGHT_FUNCS asmc_mbp_sysctl_light_left, \ - asmc_mbp_sysctl_light_right, \ - asmc_mbp_sysctl_light_control +#define ASMC_SMS_FUNCS \ + .smc_sms_x = asmc_mb_sysctl_sms_x, \ + .smc_sms_y = asmc_mb_sysctl_sms_y, \ + .smc_sms_z = asmc_mb_sysctl_sms_z + +#define ASMC_SMS_FUNCS_DISABLED \ + .smc_sms_x = NULL, \ + .smc_sms_y = NULL, \ + .smc_sms_z = NULL + +#define ASMC_FAN_FUNCS \ + .smc_fan_id = asmc_mb_sysctl_fanid, \ + .smc_fan_speed = asmc_mb_sysctl_fanspeed, \ + .smc_fan_safespeed = asmc_mb_sysctl_fansafespeed, \ + .smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \ + .smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \ + .smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed + +#define ASMC_FAN_FUNCS2 \ + .smc_fan_id = asmc_mb_sysctl_fanid, \ + .smc_fan_speed = asmc_mb_sysctl_fanspeed, \ + .smc_fan_safespeed = NULL, \ + .smc_fan_minspeed = asmc_mb_sysctl_fanminspeed, \ + .smc_fan_maxspeed = asmc_mb_sysctl_fanmaxspeed, \ + .smc_fan_targetspeed = asmc_mb_sysctl_fantargetspeed + +#define ASMC_LIGHT_FUNCS \ + .smc_light_left = asmc_mbp_sysctl_light_left, \ + .smc_light_right = asmc_mbp_sysctl_light_right, \ + .smc_light_control = asmc_mbp_sysctl_light_control #define ASMC_LIGHT_FUNCS_10BYTE \ - asmc_mbp_sysctl_light_left_10byte, \ - NULL, \ - asmc_mbp_sysctl_light_control + .smc_light_left = asmc_mbp_sysctl_light_left_10byte, \ + .smc_light_right = NULL, \ + .smc_light_control = asmc_mbp_sysctl_light_control + +#define ASMC_LIGHT_FUNCS_DISABLED \ + .smc_light_left = NULL, \ + .smc_light_right = NULL, \ + .smc_light_control = NULL -#define ASMC_LIGHT_FUNCS_DISABLED NULL, NULL, NULL +#define ASMC_TEMPS_FUNCS_DISABLED \ + .smc_temps = {}, \ + .smc_tempnames = {}, \ + .smc_tempdescs = {} \ static const struct asmc_model asmc_models[] = { { "MacBook1,1", "Apple SMC MacBook Core Duo", - ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL, + ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS }, { "MacBook2,1", "Apple SMC MacBook Core 2 Duo", - ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL, + ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, ASMC_MB_TEMPS, ASMC_MB_TEMPNAMES, ASMC_MB_TEMPDESCS }, { "MacBook3,1", "Apple SMC MacBook Core 2 Duo", - ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL, + ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, ASMC_MB31_TEMPS, ASMC_MB31_TEMPNAMES, ASMC_MB31_TEMPDESCS }, @@ -258,6 +308,12 @@ static const struct asmc_model asmc_models[] = { }, { + "MacBookPro8,3", "Apple SMC MacBook Pro (early 2011, 17-inch)", + ASMC_SMS_FUNCS, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, + ASMC_MBP83_TEMPS, ASMC_MBP83_TEMPNAMES, ASMC_MBP83_TEMPDESCS + }, + + { "MacBookPro9,1", "Apple SMC MacBook Pro (mid 2012, 15-inch)", ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, ASMC_MBP91_TEMPS, ASMC_MBP91_TEMPNAMES, ASMC_MBP91_TEMPDESCS @@ -283,16 +339,29 @@ static const struct asmc_model asmc_models[] = { { "MacBookPro11,4", "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch)", - ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, ASMC_MBP114_TEMPS, ASMC_MBP114_TEMPNAMES, ASMC_MBP114_TEMPDESCS }, + { + "MacBookPro11,5", + "Apple SMC MacBook Pro Retina Core i7 (mid 2015, 15-inch, AMD GPU)", + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, + ASMC_MBP115_TEMPS, ASMC_MBP115_TEMPNAMES, ASMC_MBP115_TEMPDESCS + }, + + { + "MacBookPro13,1", "Apple SMC MacBook Pro Retina Core i5 (late 2016, 13-inch)", + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, + ASMC_MBP131_TEMPS, ASMC_MBP131_TEMPNAMES, ASMC_MBP131_TEMPDESCS + }, + /* The Mac Mini has no SMS */ { "Macmini1,1", "Apple SMC Mac Mini", - NULL, NULL, NULL, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, - NULL, NULL, NULL, + ASMC_LIGHT_FUNCS_DISABLED, ASMC_MM_TEMPS, ASMC_MM_TEMPNAMES, ASMC_MM_TEMPDESCS }, @@ -308,9 +377,9 @@ static const struct asmc_model asmc_models[] = { /* The Mac Mini 3,1 has no SMS */ { "Macmini3,1", "Apple SMC Mac Mini 3,1", - NULL, NULL, NULL, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, - NULL, NULL, NULL, + ASMC_LIGHT_FUNCS_DISABLED, ASMC_MM31_TEMPS, ASMC_MM31_TEMPNAMES, ASMC_MM31_TEMPDESCS }, @@ -318,7 +387,7 @@ static const struct asmc_model asmc_models[] = { { "Macmini4,1", "Apple SMC Mac mini 4,1 (Mid-2010)", ASMC_SMS_FUNCS_DISABLED, - ASMC_FAN_FUNCS, + ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS_DISABLED, ASMC_MM41_TEMPS, ASMC_MM41_TEMPNAMES, ASMC_MM41_TEMPDESCS }, @@ -327,18 +396,18 @@ static const struct asmc_model asmc_models[] = { /* - same sensors as Mac Mini 5,2 */ { "Macmini5,1", "Apple SMC Mac Mini 5,1", - NULL, NULL, NULL, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, - NULL, NULL, NULL, + ASMC_LIGHT_FUNCS_DISABLED, ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS }, /* The Mac Mini 5,2 has no SMS */ { "Macmini5,2", "Apple SMC Mac Mini 5,2", - NULL, NULL, NULL, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, - NULL, NULL, NULL, + ASMC_LIGHT_FUNCS_DISABLED, ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS }, @@ -346,63 +415,72 @@ static const struct asmc_model asmc_models[] = { /* - same sensors as Mac Mini 5,2 */ { "Macmini5,3", "Apple SMC Mac Mini 5,3", - NULL, NULL, NULL, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, - NULL, NULL, NULL, + ASMC_LIGHT_FUNCS_DISABLED, ASMC_MM52_TEMPS, ASMC_MM52_TEMPNAMES, ASMC_MM52_TEMPDESCS }, /* The Mac Mini 6,1 has no SMS */ { "Macmini6,1", "Apple SMC Mac Mini 6,1", - NULL, NULL, NULL, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, - NULL, NULL, NULL, + ASMC_LIGHT_FUNCS_DISABLED, ASMC_MM61_TEMPS, ASMC_MM61_TEMPNAMES, ASMC_MM61_TEMPDESCS }, /* The Mac Mini 6,2 has no SMS */ { "Macmini6,2", "Apple SMC Mac Mini 6,2", - NULL, NULL, NULL, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, - NULL, NULL, NULL, + ASMC_LIGHT_FUNCS_DISABLED, ASMC_MM62_TEMPS, ASMC_MM62_TEMPNAMES, ASMC_MM62_TEMPDESCS }, /* The Mac Mini 7,1 has no SMS */ { "Macmini7,1", "Apple SMC Mac Mini 7,1", - NULL, NULL, NULL, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS2, - NULL, NULL, NULL, + ASMC_LIGHT_FUNCS_DISABLED, ASMC_MM71_TEMPS, ASMC_MM71_TEMPNAMES, ASMC_MM71_TEMPDESCS }, /* Idem for the Mac Pro "Quad Core" (original) */ { "MacPro1,1", "Apple SMC Mac Pro (Quad Core)", - NULL, NULL, NULL, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, - NULL, NULL, NULL, + ASMC_LIGHT_FUNCS_DISABLED, ASMC_MP1_TEMPS, ASMC_MP1_TEMPNAMES, ASMC_MP1_TEMPDESCS }, + /* Idem for the Mac Pro (Early 2008) */ + { + "MacPro3,1", "Apple SMC Mac Pro (Early 2008)", + ASMC_SMS_FUNCS_DISABLED, + ASMC_FAN_FUNCS, + ASMC_LIGHT_FUNCS_DISABLED, + ASMC_MP31_TEMPS, ASMC_MP31_TEMPNAMES, ASMC_MP31_TEMPDESCS + }, + /* Idem for the Mac Pro (8-core) */ { "MacPro2", "Apple SMC Mac Pro (8-core)", - NULL, NULL, NULL, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, - NULL, NULL, NULL, + ASMC_LIGHT_FUNCS_DISABLED, ASMC_MP2_TEMPS, ASMC_MP2_TEMPNAMES, ASMC_MP2_TEMPDESCS }, /* Idem for the MacPro 2010*/ { "MacPro5,1", "Apple SMC MacPro (2010)", - NULL, NULL, NULL, + ASMC_SMS_FUNCS_DISABLED, ASMC_FAN_FUNCS, - NULL, NULL, NULL, + ASMC_LIGHT_FUNCS_DISABLED, ASMC_MP5_TEMPS, ASMC_MP5_TEMPNAMES, ASMC_MP5_TEMPDESCS }, @@ -417,20 +495,20 @@ static const struct asmc_model asmc_models[] = { { "MacBookAir1,1", "Apple SMC MacBook Air", - ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL, + ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, ASMC_MBA_TEMPS, ASMC_MBA_TEMPNAMES, ASMC_MBA_TEMPDESCS }, { "MacBookAir3,1", "Apple SMC MacBook Air Core 2 Duo (Late 2010)", - ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, NULL, NULL, NULL, + ASMC_SMS_FUNCS, ASMC_FAN_FUNCS, ASMC_LIGHT_FUNCS_DISABLED, ASMC_MBA3_TEMPS, ASMC_MBA3_TEMPNAMES, ASMC_MBA3_TEMPDESCS }, { "MacBookAir4,1", "Apple SMC Macbook Air 11-inch (Mid 2011)", ASMC_SMS_FUNCS_DISABLED, - ASMC_FAN_FUNCS2, + ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS }, @@ -438,7 +516,7 @@ static const struct asmc_model asmc_models[] = { { "MacBookAir4,2", "Apple SMC Macbook Air 13-inch (Mid 2011)", ASMC_SMS_FUNCS_DISABLED, - ASMC_FAN_FUNCS2, + ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, ASMC_MBA4_TEMPS, ASMC_MBA4_TEMPNAMES, ASMC_MBA4_TEMPDESCS }, @@ -485,8 +563,42 @@ static const struct asmc_model asmc_models[] = { ASMC_FAN_FUNCS2, ASMC_LIGHT_FUNCS, ASMC_MBA7_TEMPS, ASMC_MBA7_TEMPNAMES, ASMC_MBA7_TEMPDESCS + } +}; + +static const struct asmc_model asmc_generic_models[] = { + { + .smc_model = "MacBookAir", + .smc_desc = NULL, + ASMC_SMS_FUNCS_DISABLED, + ASMC_FAN_FUNCS2, + ASMC_LIGHT_FUNCS, + ASMC_TEMPS_FUNCS_DISABLED + }, + { + .smc_model = "MacBookPro", + .smc_desc = NULL, + ASMC_SMS_FUNCS_DISABLED, + ASMC_FAN_FUNCS2, + ASMC_LIGHT_FUNCS, + ASMC_TEMPS_FUNCS_DISABLED + }, + { + .smc_model = "MacPro", + .smc_desc = NULL, + ASMC_SMS_FUNCS_DISABLED, + ASMC_FAN_FUNCS2, + ASMC_LIGHT_FUNCS_DISABLED, + ASMC_TEMPS_FUNCS_DISABLED }, - { NULL, NULL } + { + .smc_model = "Macmini", + .smc_desc = NULL, + ASMC_SMS_FUNCS_DISABLED, + ASMC_FAN_FUNCS2, + ASMC_LIGHT_FUNCS_DISABLED, + ASMC_TEMPS_FUNCS_DISABLED + } }; #undef ASMC_SMS_FUNCS @@ -503,7 +615,13 @@ static device_method_t asmc_methods[] = { DEVMETHOD(device_attach, asmc_attach), DEVMETHOD(device_detach, asmc_detach), DEVMETHOD(device_resume, asmc_resume), - { 0, 0 } + + /* Backlight interface */ + DEVMETHOD(backlight_update_status, asmc_backlight_update_status), + DEVMETHOD(backlight_get_status, asmc_backlight_get_status), + DEVMETHOD(backlight_get_info, asmc_backlight_get_info), + + DEVMETHOD_END }; static driver_t asmc_driver = { @@ -518,9 +636,9 @@ static driver_t asmc_driver = { #define _COMPONENT ACPI_OEM ACPI_MODULE_NAME("ASMC") #ifdef ASMC_DEBUG -#define ASMC_DPRINTF(str) device_printf(dev, str) +#define ASMC_DPRINTF(str, ...) device_printf(dev, str, ##__VA_ARGS__) #else -#define ASMC_DPRINTF(str) +#define ASMC_DPRINTF(str, ...) #endif /* NB: can't be const */ @@ -528,34 +646,49 @@ static char *asmc_ids[] = { "APP0001", NULL }; static unsigned int light_control = 0; +ACPI_PNP_INFO(asmc_ids); DRIVER_MODULE(asmc, acpi, asmc_driver, NULL, NULL); MODULE_DEPEND(asmc, acpi, 1, 1, 1); +MODULE_DEPEND(asmc, backlight, 1, 1, 1); static const struct asmc_model * asmc_match(device_t dev) { + const struct asmc_model *model; + char *model_name; int i; - char *model; - model = kern_getenv("smbios.system.product"); - if (model == NULL) - return (NULL); + model = NULL; - for (i = 0; asmc_models[i].smc_model; i++) { - if (!strncmp(model, asmc_models[i].smc_model, strlen(model))) { - freeenv(model); - return (&asmc_models[i]); + model_name = kern_getenv("smbios.system.product"); + if (model_name == NULL) + goto out; + + for (i = 0; i < nitems(asmc_models); i++) { + if (strncmp(model_name, asmc_models[i].smc_model, + strlen(model_name)) == 0) { + model = &asmc_models[i]; + goto out; + } + } + for (i = 0; i < nitems(asmc_generic_models); i++) { + if (strncmp(model_name, asmc_generic_models[i].smc_model, + strlen(asmc_generic_models[i].smc_model)) == 0) { + model = &asmc_generic_models[i]; + goto out; } } - freeenv(model); - return (NULL); +out: + freeenv(model_name); + return (model); } static int asmc_probe(device_t dev) { const struct asmc_model *model; + const char *device_desc; int rv; if (resource_disabled("asmc", 0)) @@ -565,11 +698,13 @@ asmc_probe(device_t dev) return (rv); model = asmc_match(dev); - if (!model) { + if (model == NULL) { device_printf(dev, "model not recognized\n"); return (ENXIO); } - device_set_desc(dev, model->smc_desc); + device_desc = model->smc_desc == NULL ? + model->smc_model : model->smc_desc; + device_set_desc(dev, device_desc); return (rv); } @@ -592,7 +727,7 @@ asmc_attach(device_t dev) return (ENOMEM); } - sysctlctx = device_get_sysctl_ctx(dev); + sysctlctx = device_get_sysctl_ctx(dev); sysctlnode = device_get_sysctl_tree(dev); model = asmc_match(dev); @@ -614,57 +749,50 @@ asmc_attach(device_t dev) name[0] = '0' + j; name[1] = 0; sc->sc_fan_tree[i] = SYSCTL_ADD_NODE(sysctlctx, - SYSCTL_CHILDREN(sc->sc_fan_tree[0]), - OID_AUTO, name, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, - "Fan Subtree"); + SYSCTL_CHILDREN(sc->sc_fan_tree[0]), OID_AUTO, name, + CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Fan Subtree"); SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_fan_tree[i]), OID_AUTO, "id", - CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, - dev, j, model->smc_fan_id, "I", - "Fan ID"); + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, + model->smc_fan_id, "I", "Fan ID"); SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_fan_tree[i]), OID_AUTO, "speed", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, - dev, j, model->smc_fan_speed, "I", - "Fan speed in RPM"); + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, + model->smc_fan_speed, "I", "Fan speed in RPM"); SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_fan_tree[i]), OID_AUTO, "safespeed", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, - dev, j, model->smc_fan_safespeed, "I", - "Fan safe speed in RPM"); + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, j, + model->smc_fan_safespeed, "I", "Fan safe speed in RPM"); SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_fan_tree[i]), OID_AUTO, "minspeed", - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, - dev, j, model->smc_fan_minspeed, "I", - "Fan minimum speed in RPM"); + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, + model->smc_fan_minspeed, "I", "Fan minimum speed in RPM"); SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_fan_tree[i]), OID_AUTO, "maxspeed", - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, - dev, j, model->smc_fan_maxspeed, "I", - "Fan maximum speed in RPM"); + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, + model->smc_fan_maxspeed, "I", "Fan maximum speed in RPM"); SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_fan_tree[i]), OID_AUTO, "targetspeed", - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, - dev, j, model->smc_fan_targetspeed, "I", - "Fan target speed in RPM"); + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, + model->smc_fan_targetspeed, "I", "Fan target speed in RPM"); SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_fan_tree[i]), OID_AUTO, "manual", - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, - dev, j, asmc_mb_sysctl_fanmanual, "I", + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, dev, j, + asmc_mb_sysctl_fanmanual, "I", "Fan manual mode (0=auto, 1=manual)"); } @@ -679,8 +807,8 @@ asmc_attach(device_t dev) SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_temp_tree), OID_AUTO, model->smc_tempnames[i], - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, - dev, i, asmc_temp_sysctl, "I", + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, i, + asmc_temp_sysctl, "I", model->smc_tempdescs[i]); } @@ -696,26 +824,69 @@ asmc_attach(device_t dev) SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_light_tree), OID_AUTO, "left", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0, model->smc_light_left, "I", "Keyboard backlight left sensor"); SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_light_tree), OID_AUTO, "right", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, - dev, 0, model->smc_light_right, "I", + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0, + model->smc_light_right, "I", "Keyboard backlight right sensor"); SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_light_tree), OID_AUTO, "control", - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | - CTLFLAG_NEEDGIANT, dev, 0, - model->smc_light_control, "I", + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, + dev, 0, model->smc_light_control, "I", "Keyboard backlight brightness control"); + + sc->sc_kbd_bkl = backlight_register("asmc", dev); + if (sc->sc_kbd_bkl == NULL) { + device_printf(dev, "Can not register backlight\n"); + ret = ENXIO; + goto err; + } } +#ifdef ASMC_DEBUG + /* + * Raw SMC key access for debugging. + */ + sc->sc_raw_tree = SYSCTL_ADD_NODE(sysctlctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "raw", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Raw SMC key access"); + + SYSCTL_ADD_PROC(sysctlctx, + SYSCTL_CHILDREN(sc->sc_raw_tree), + OID_AUTO, "key", + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, + dev, 0, asmc_raw_key_sysctl, "A", + "SMC key name (4 chars)"); + + SYSCTL_ADD_PROC(sysctlctx, + SYSCTL_CHILDREN(sc->sc_raw_tree), + OID_AUTO, "value", + CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, + dev, 0, asmc_raw_value_sysctl, "A", + "SMC key value (hex string)"); + + SYSCTL_ADD_PROC(sysctlctx, + SYSCTL_CHILDREN(sc->sc_raw_tree), + OID_AUTO, "len", + CTLTYPE_U8 | CTLFLAG_RD | CTLFLAG_MPSAFE, + dev, 0, asmc_raw_len_sysctl, "CU", + "SMC key value length"); + + SYSCTL_ADD_PROC(sysctlctx, + SYSCTL_CHILDREN(sc->sc_raw_tree), + OID_AUTO, "type", + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, + dev, 0, asmc_raw_type_sysctl, "A", + "SMC key type (4 chars)"); +#endif + if (model->smc_sms_x == NULL) goto nosms; @@ -729,21 +900,21 @@ asmc_attach(device_t dev) SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_sms_tree), OID_AUTO, "x", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0, model->smc_sms_x, "I", "Sudden Motion Sensor X value"); SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_sms_tree), OID_AUTO, "y", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0, model->smc_sms_y, "I", "Sudden Motion Sensor Y value"); SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(sc->sc_sms_tree), OID_AUTO, "z", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, dev, 0, model->smc_sms_z, "I", "Sudden Motion Sensor Z value"); @@ -767,33 +938,26 @@ asmc_attach(device_t dev) * Allocate an IRQ for the SMS. */ sc->sc_rid_irq = 0; - sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &sc->sc_rid_irq, RF_ACTIVE); + sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_rid_irq, + RF_ACTIVE); if (sc->sc_irq == NULL) { device_printf(dev, "unable to allocate IRQ resource\n"); ret = ENXIO; - goto err2; + goto err; } - ret = bus_setup_intr(dev, sc->sc_irq, - INTR_TYPE_MISC | INTR_MPSAFE, - asmc_sms_intrfast, NULL, - dev, &sc->sc_cookie); - + ret = bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE, + asmc_sms_intrfast, NULL, dev, &sc->sc_cookie); if (ret) { device_printf(dev, "unable to setup SMS IRQ\n"); - goto err1; + goto err; } + nosms: return (0); -err1: - bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq, sc->sc_irq); -err2: - bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port, - sc->sc_ioport); - mtx_destroy(&sc->sc_mtx); - if (sc->sc_sms_tq) - taskqueue_free(sc->sc_sms_tq); + +err: + asmc_detach(dev); return (ret); } @@ -803,19 +967,41 @@ asmc_detach(device_t dev) { struct asmc_softc *sc = device_get_softc(dev); + if (sc->sc_kbd_bkl != NULL) + backlight_destroy(sc->sc_kbd_bkl); + + /* Free sensor key arrays */ + for (int i = 0; i < sc->sc_voltage_count; i++) + free(sc->sc_voltage_sensors[i], M_DEVBUF); + for (int i = 0; i < sc->sc_current_count; i++) + free(sc->sc_current_sensors[i], M_DEVBUF); + for (int i = 0; i < sc->sc_power_count; i++) + free(sc->sc_power_sensors[i], M_DEVBUF); + for (int i = 0; i < sc->sc_light_count; i++) + free(sc->sc_light_sensors[i], M_DEVBUF); + if (sc->sc_sms_tq) { taskqueue_drain(sc->sc_sms_tq, &sc->sc_sms_task); taskqueue_free(sc->sc_sms_tq); + sc->sc_sms_tq = NULL; } - if (sc->sc_cookie) + if (sc->sc_cookie) { bus_teardown_intr(dev, sc->sc_irq, sc->sc_cookie); - if (sc->sc_irq) + sc->sc_cookie = NULL; + } + if (sc->sc_irq) { bus_release_resource(dev, SYS_RES_IRQ, sc->sc_rid_irq, sc->sc_irq); - if (sc->sc_ioport) + sc->sc_irq = NULL; + } + if (sc->sc_ioport) { bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid_port, sc->sc_ioport); - mtx_destroy(&sc->sc_mtx); + sc->sc_ioport = NULL; + } + if (mtx_initialized(&sc->sc_mtx)) { + mtx_destroy(&sc->sc_mtx); + } return (0); } @@ -823,15 +1009,18 @@ asmc_detach(device_t dev) static int asmc_resume(device_t dev) { - uint8_t buf[2]; - buf[0] = light_control; - buf[1] = 0x00; - asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof buf); - return (0); + uint8_t buf[2]; + + buf[0] = light_control; + buf[1] = 0x00; + asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); + + return (0); } #ifdef ASMC_DEBUG -void asmc_dumpall(device_t dev) +void +asmc_dumpall(device_t dev) { struct asmc_softc *sc = device_get_softc(dev); int i; @@ -851,8 +1040,17 @@ static int asmc_init(device_t dev) { struct asmc_softc *sc = device_get_softc(dev); + struct sysctl_ctx_list *sysctlctx; + uint8_t buf[6]; int i, error = 1; - uint8_t buf[4]; + + sysctlctx = device_get_sysctl_ctx(dev); + + error = asmc_key_read(dev, ASMC_KEY_REV, buf, 6); + if (error != 0) + goto out_err; + device_printf(dev, "SMC revision: %x.%x%x%x\n", buf[0], buf[1], buf[2], + ntohs(*(uint16_t *)buf + 4)); if (sc->sc_model->smc_sms_x == NULL) goto nosms; @@ -923,10 +1121,21 @@ asmc_init(device_t dev) out: asmc_sms_calibrate(dev); nosms: + /* Wake-on-LAN convenience sysctl */ + if (asmc_key_read(dev, ASMC_KEY_AUPO, buf, 1) == 0) { + SYSCTL_ADD_PROC(sysctlctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), + OID_AUTO, "wol", + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, + dev, 0, asmc_wol_sysctl, "I", + "Wake-on-LAN enable (0=off, 1=on)"); + } + sc->sc_nfan = asmc_fan_count(dev); if (sc->sc_nfan > ASMC_MAXFANS) { - device_printf(dev, "more than %d fans were detected. Please " - "report this.\n", ASMC_MAXFANS); + device_printf(dev, + "more than %d fans were detected. Please report this.\n", + ASMC_MAXFANS); sc->sc_nfan = ASMC_MAXFANS; } @@ -936,15 +1145,22 @@ nosms: if (asmc_key_read(dev, ASMC_NKEYS, buf, 4) == 0) { sc->sc_nkeys = be32dec(buf); if (bootverbose) - device_printf(dev, "number of keys: %d\n", sc->sc_nkeys); + device_printf(dev, "number of keys: %d\n", + sc->sc_nkeys); } else { sc->sc_nkeys = 0; } + /* + * Auto-detect and register voltage/current/power/ambient sensors. + * Scans SMC keys and creates sysctls for detected sensors. + */ + asmc_detect_sensors(dev); + +out_err: #ifdef ASMC_DEBUG asmc_dumpall(dev); #endif - return (error); } @@ -985,12 +1201,9 @@ asmc_wait(device_t dev, uint8_t val) #ifdef ASMC_DEBUG sc = device_get_softc(dev); -#endif - val = val & ASMC_STATUS_MASK; -#ifdef ASMC_DEBUG - device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, val, - ASMC_CMDPORT_READ(sc)); + device_printf(dev, "%s failed: 0x%x, 0x%x\n", __func__, + val & ASMC_STATUS_MASK, ASMC_CMDPORT_READ(sc)); #endif return (1); } @@ -1000,11 +1213,12 @@ asmc_wait(device_t dev, uint8_t val) * the acknowledgement fails. */ static int -asmc_command(device_t dev, uint8_t command) { +asmc_command(device_t dev, uint8_t command) +{ int i; struct asmc_softc *sc = device_get_softc(dev); - for (i=0; i < 10; i++) { + for (i = 0; i < 10; i++) { ASMC_CMDPORT_WRITE(sc, command); if (asmc_wait_ack(dev, 0x0c, 100) == 0) { return (0); @@ -1047,9 +1261,10 @@ begin: error = 0; out: if (error) { - if (++try < 10) goto begin; - device_printf(dev,"%s for key %s failed %d times, giving up\n", - __func__, key, try); + if (++try < 10) + goto begin; + device_printf(dev, "%s for key %s failed %d times, giving up\n", + __func__, key, try); } mtx_unlock_spin(&sc->sc_mtx); @@ -1062,10 +1277,10 @@ static int asmc_key_dump(device_t dev, int number) { struct asmc_softc *sc = device_get_softc(dev); - char key[5] = { 0 }; - char type[7] = { 0 }; + char key[ASMC_KEYLEN + 1] = { 0 }; + char type[ASMC_KEYINFO_RESPLEN + 1] = { 0 }; uint8_t index[4]; - uint8_t v[32]; + uint8_t v[ASMC_MAXVAL]; uint8_t maxlen; int i, error = 1, try = 0; @@ -1074,40 +1289,40 @@ asmc_key_dump(device_t dev, int number) index[0] = (number >> 24) & 0xff; index[1] = (number >> 16) & 0xff; index[2] = (number >> 8) & 0xff; - index[3] = (number) & 0xff; + index[3] = number & 0xff; begin: - if (asmc_command(dev, 0x12)) + if (asmc_command(dev, ASMC_CMDGETBYINDEX)) goto out; - for (i = 0; i < 4; i++) { + for (i = 0; i < ASMC_KEYLEN; i++) { ASMC_DATAPORT_WRITE(sc, index[i]); - if (asmc_wait(dev, 0x04)) + if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) goto out; } - ASMC_DATAPORT_WRITE(sc, 4); + ASMC_DATAPORT_WRITE(sc, ASMC_KEYLEN); - for (i = 0; i < 4; i++) { - if (asmc_wait(dev, 0x05)) + for (i = 0; i < ASMC_KEYLEN; i++) { + if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) goto out; key[i] = ASMC_DATAPORT_READ(sc); } - /* get type */ - if (asmc_command(dev, 0x13)) + /* Get key info (length + type). */ + if (asmc_command(dev, ASMC_CMDGETINFO)) goto out; - for (i = 0; i < 4; i++) { + for (i = 0; i < ASMC_KEYLEN; i++) { ASMC_DATAPORT_WRITE(sc, key[i]); - if (asmc_wait(dev, 0x04)) + if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) goto out; } - ASMC_DATAPORT_WRITE(sc, 6); + ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN); - for (i = 0; i < 6; i++) { - if (asmc_wait(dev, 0x05)) + for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) { + if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) goto out; type[i] = ASMC_DATAPORT_READ(sc); } @@ -1115,41 +1330,599 @@ begin: error = 0; out: if (error) { - if (++try < 10) goto begin; - device_printf(dev,"%s for key %s failed %d times, giving up\n", - __func__, key, try); - mtx_unlock_spin(&sc->sc_mtx); + if (++try < ASMC_MAXRETRIES) + goto begin; + device_printf(dev, + "%s for key %d failed %d times, giving up\n", + __func__, number, try); + } + mtx_unlock_spin(&sc->sc_mtx); + + if (error) + return (error); + + maxlen = type[0]; + type[0] = ' '; + type[5] = '\0'; + if (maxlen > sizeof(v)) + maxlen = sizeof(v); + + memset(v, 0, sizeof(v)); + error = asmc_key_read(dev, key, v, maxlen); + if (error) + return (error); + + device_printf(dev, "key %d: %s, type%s (len %d), data", + number, key, type, maxlen); + for (i = 0; i < maxlen; i++) + printf(" %02x", v[i]); + printf("\n"); + + return (0); +} +#endif /* ASMC_DEBUG */ + +/* + * Get key info (length and type) from SMC using command 0x13. + * If len is non-NULL, stores the key's value length. + * If type is non-NULL, stores the 4-char type string (must be at least 5 bytes). + */ +static int +asmc_key_getinfo(device_t dev, const char *key, uint8_t *len, char *type) +{ + struct asmc_softc *sc = device_get_softc(dev); + uint8_t info[ASMC_KEYINFO_RESPLEN]; + int i, error = -1, try = 0; + + mtx_lock_spin(&sc->sc_mtx); + +begin: + if (asmc_command(dev, ASMC_CMDGETINFO)) + goto out; + + for (i = 0; i < ASMC_KEYLEN; i++) { + ASMC_DATAPORT_WRITE(sc, key[i]); + if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) + goto out; + } + + ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN); + + for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) { + if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) + goto out; + info[i] = ASMC_DATAPORT_READ(sc); + } + + error = 0; +out: + if (error && ++try < ASMC_MAXRETRIES) + goto begin; + mtx_unlock_spin(&sc->sc_mtx); + + if (error == 0) { + if (len != NULL) + *len = info[0]; + if (type != NULL) { + for (i = 0; i < ASMC_TYPELEN; i++) + type[i] = info[i + 1]; + type[ASMC_TYPELEN] = '\0'; + } + } + return (error); +} + +#ifdef ASMC_DEBUG +/* + * Raw SMC key access sysctls - enables reading/writing any SMC key by name + * Usage: + * sysctl dev.asmc.0.raw.key=AUPO # Set key, auto-detects length + * sysctl dev.asmc.0.raw.value # Read current value (hex bytes) + * sysctl dev.asmc.0.raw.value=01 # Write new value + */ +static int +asmc_raw_key_sysctl(SYSCTL_HANDLER_ARGS) +{ + device_t dev = (device_t) arg1; + struct asmc_softc *sc = device_get_softc(dev); + char newkey[ASMC_KEYLEN + 1]; + uint8_t keylen; + int error; + + strlcpy(newkey, sc->sc_rawkey, sizeof(newkey)); + error = sysctl_handle_string(oidp, newkey, sizeof(newkey), req); + if (error || req->newptr == NULL) + return (error); + + if (strlen(newkey) != ASMC_KEYLEN) + return (EINVAL); + + /* Get key info to auto-detect length and type */ + if (asmc_key_getinfo(dev, newkey, &keylen, sc->sc_rawtype) != 0) + return (ENOENT); + + if (keylen > ASMC_MAXVAL) + keylen = ASMC_MAXVAL; + + strlcpy(sc->sc_rawkey, newkey, sizeof(sc->sc_rawkey)); + sc->sc_rawlen = keylen; + memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval)); + + /* Read the key value */ + asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval, sc->sc_rawlen); + + return (0); +} + +static int +asmc_raw_value_sysctl(SYSCTL_HANDLER_ARGS) +{ + device_t dev = (device_t) arg1; + struct asmc_softc *sc = device_get_softc(dev); + char hexbuf[ASMC_MAXVAL * 2 + 1]; + int error, i; + + /* Refresh from SMC if a key has been selected. */ + if (sc->sc_rawkey[0] != '\0') { + asmc_key_read(dev, sc->sc_rawkey, sc->sc_rawval, + sc->sc_rawlen > 0 ? sc->sc_rawlen : ASMC_MAXVAL); + } + + /* Format as hex string */ + for (i = 0; i < sc->sc_rawlen && i < ASMC_MAXVAL; i++) + snprintf(hexbuf + i * 2, 3, "%02x", sc->sc_rawval[i]); + hexbuf[i * 2] = '\0'; + + error = sysctl_handle_string(oidp, hexbuf, sizeof(hexbuf), req); + if (error || req->newptr == NULL) + return (error); + + /* Reject writes until a key is selected via raw.key. */ + if (sc->sc_rawkey[0] == '\0') + return (EINVAL); + + memset(sc->sc_rawval, 0, sizeof(sc->sc_rawval)); + for (i = 0; i < sc->sc_rawlen && hexbuf[i*2] && hexbuf[i*2+1]; i++) { + unsigned int val; + char tmp[3] = { hexbuf[i*2], hexbuf[i*2+1], 0 }; + if (sscanf(tmp, "%02x", &val) == 1) + sc->sc_rawval[i] = (uint8_t)val; + } + + if (asmc_key_write(dev, sc->sc_rawkey, sc->sc_rawval, sc->sc_rawlen) != 0) + return (EIO); + + return (0); +} + +static int +asmc_raw_len_sysctl(SYSCTL_HANDLER_ARGS) +{ + device_t dev = (device_t) arg1; + struct asmc_softc *sc = device_get_softc(dev); + + return (sysctl_handle_8(oidp, &sc->sc_rawlen, 0, req)); +} + +static int +asmc_raw_type_sysctl(SYSCTL_HANDLER_ARGS) +{ + device_t dev = (device_t) arg1; + struct asmc_softc *sc = device_get_softc(dev); + + return (sysctl_handle_string(oidp, sc->sc_rawtype, + sizeof(sc->sc_rawtype), req)); +} +#endif + +/* + * Convert signed fixed-point SMC values to milli-units. + * Format "spXY" means signed with X integer bits and Y fraction bits. + */ +static int +asmc_sp78_to_milli(const uint8_t *buf) +{ + int16_t val = (int16_t)be16dec(buf); + + return ((int)val * 1000) / 256; +} + +static int +asmc_sp87_to_milli(const uint8_t *buf) +{ + int16_t val = (int16_t)be16dec(buf); + + return ((int)val * 1000) / 128; +} + +static int +asmc_sp4b_to_milli(const uint8_t *buf) +{ + int16_t val = (int16_t)be16dec(buf); + + return ((int)val * 1000) / 2048; +} + +static int +asmc_sp5a_to_milli(const uint8_t *buf) +{ + int16_t val = (int16_t)be16dec(buf); + + return ((int)val * 1000) / 1024; +} + +static int +asmc_sp69_to_milli(const uint8_t *buf) +{ + int16_t val = (int16_t)be16dec(buf); + + return ((int)val * 1000) / 512; +} + +static int +asmc_sp96_to_milli(const uint8_t *buf) +{ + int16_t val = (int16_t)be16dec(buf); + + return ((int)val * 1000) / 64; +} + +static int +asmc_sp2d_to_milli(const uint8_t *buf) +{ + int16_t val = (int16_t)be16dec(buf); + + return ((int)val * 1000) / 8192; +} + +static bool +asmc_sensor_type_supported(const char *type) +{ + + return (strncmp(type, "sp78", 4) == 0 || + strncmp(type, "sp87", 4) == 0 || + strncmp(type, "sp4b", 4) == 0 || + strncmp(type, "sp5a", 4) == 0 || + strncmp(type, "sp69", 4) == 0 || + strncmp(type, "sp96", 4) == 0 || + strncmp(type, "sp2d", 4) == 0 || + strncmp(type, "ui16", 4) == 0); +} + +/* + * Generic sensor value reader with automatic type conversion. + * Reads an SMC key, detects its type, and converts to millivalue. + */ +static int +asmc_sensor_read(device_t dev, const char *key, int *millivalue) +{ + uint8_t buf[2]; + char type[ASMC_TYPELEN + 1]; + uint8_t len; + int error; + + error = asmc_key_getinfo(dev, key, &len, type); + if (error != 0) + return (error); + + if (len != 2) { + if (bootverbose) + device_printf(dev, + "%s: key %s unexpected length %d\n", + __func__, key, len); + return (ENXIO); } - else { - char buf[1024]; - char buf2[8]; - mtx_unlock_spin(&sc->sc_mtx); - maxlen = type[0]; - type[0] = ' '; - type[5] = 0; - if (maxlen > sizeof(v)) { + + error = asmc_key_read(dev, key, buf, sizeof(buf)); + if (error != 0) + return (error); + + if (strncmp(type, "sp78", 4) == 0) { + *millivalue = asmc_sp78_to_milli(buf); + } else if (strncmp(type, "sp87", 4) == 0) { + *millivalue = asmc_sp87_to_milli(buf); + } else if (strncmp(type, "sp4b", 4) == 0) { + *millivalue = asmc_sp4b_to_milli(buf); + } else if (strncmp(type, "sp5a", 4) == 0) { + *millivalue = asmc_sp5a_to_milli(buf); + } else if (strncmp(type, "sp69", 4) == 0) { + *millivalue = asmc_sp69_to_milli(buf); + } else if (strncmp(type, "sp96", 4) == 0) { + *millivalue = asmc_sp96_to_milli(buf); + } else if (strncmp(type, "sp2d", 4) == 0) { + *millivalue = asmc_sp2d_to_milli(buf); + } else if (strncmp(type, "ui16", 4) == 0) { + *millivalue = be16dec(buf); + } else { + if (bootverbose) device_printf(dev, - "WARNING: cropping maxlen from %d to %zu\n", - maxlen, sizeof(v)); - maxlen = sizeof(v); + "%s: unknown type '%s' for key %s\n", + __func__, type, key); + return (ENXIO); + } + + return (0); +} + +/* + * Generic sensor sysctl handler for voltage/current/power/light sensors. + * arg2 encodes: sensor_type (high byte) | sensor_index (low byte) + * Sensor types: 'V'=voltage, 'I'=current, 'P'=power, 'L'=light + */ +static int +asmc_sensor_sysctl(SYSCTL_HANDLER_ARGS) +{ + device_t dev = (device_t) arg1; + struct asmc_softc *sc = device_get_softc(dev); + int error, val; + int sensor_type = (arg2 >> 8) & 0xFF; + int sensor_idx = arg2 & 0xFF; + const char *key = NULL; + + /* Select sensor based on type and index */ + switch (sensor_type) { + case 'V': /* Voltage */ + if (sensor_idx < sc->sc_voltage_count) + key = sc->sc_voltage_sensors[sensor_idx]; + break; + case 'I': /* Current */ + if (sensor_idx < sc->sc_current_count) + key = sc->sc_current_sensors[sensor_idx]; + break; + case 'P': /* Power */ + if (sensor_idx < sc->sc_power_count) + key = sc->sc_power_sensors[sensor_idx]; + break; + case 'L': /* Light */ + if (sensor_idx < sc->sc_light_count) + key = sc->sc_light_sensors[sensor_idx]; + break; + default: + return (EINVAL); + } + + if (key == NULL) + return (ENOENT); + + error = asmc_sensor_read(dev, key, &val); + if (error != 0) + return (error); + + return (sysctl_handle_int(oidp, &val, 0, req)); +} + +/* + * Detect and register voltage/current/power/ambient sensors. + * Scans all SMC keys and identifies sensor keys by prefix. + * Returns 0 on success, -1 on error. + */ +static int +asmc_detect_sensors(device_t dev) +{ + struct asmc_softc *sc = device_get_softc(dev); + struct sysctl_ctx_list *sysctlctx; + struct sysctl_oid *tree_node; + char key[ASMC_KEYLEN + 1]; + char type[ASMC_TYPELEN + 1]; + uint8_t len; + unsigned int nkeys; + unsigned int i; + int error; + char *sensor_key; + + /* Initialize counts */ + sc->sc_voltage_count = 0; + sc->sc_current_count = 0; + sc->sc_power_count = 0; + sc->sc_light_count = 0; + + if (sc->sc_nkeys == 0) + return (0); + nkeys = sc->sc_nkeys; + + /* Scan all keys for voltage/current/power/ambient light sensors */ + for (i = 0; i < nkeys; i++) { + /* Get key name by index */ + error = asmc_key_dump_by_index(dev, i, key, type, &len); + if (error != 0) + continue; + if (!asmc_sensor_type_supported(type)) + continue; + + /* Voltage sensors (VC*, VD*, VG*, VP*, VI*) */ + if (key[0] == 'V' && (key[1] == 'C' || key[1] == 'D' || + key[1] == 'G' || key[1] == 'P' || key[1] == 'I') && + len == 2) { + if (sc->sc_voltage_count >= ASMC_MAX_SENSORS) + continue; + sensor_key = malloc(ASMC_KEYLEN + 1, + M_DEVBUF, M_WAITOK); + memcpy(sensor_key, key, ASMC_KEYLEN + 1); + sc->sc_voltage_sensors[sc->sc_voltage_count++] = + sensor_key; + } else if (key[0] == 'I' && (key[1] == 'C' || + key[1] == 'D' || key[1] == 'G' || key[1] == 'M' || + key[1] == 'N' || key[1] == 'O' || key[1] == 'H' || + key[1] == 'P' || key[1] == 'B' || key[1] == 'A' || + key[1] == 'L') && len == 2) { + /* Current sensors */ + if (sc->sc_current_count >= ASMC_MAX_SENSORS) + continue; + sensor_key = malloc(ASMC_KEYLEN + 1, + M_DEVBUF, M_WAITOK); + memcpy(sensor_key, key, ASMC_KEYLEN + 1); + sc->sc_current_sensors[sc->sc_current_count++] = + sensor_key; + } else if (key[0] == 'P' && (key[1] == 'C' || + key[1] == 'D' || key[1] == 'N' || key[1] == 'S' || + key[1] == 'T' || key[1] == 'H' || key[1] == 'F' || + key[1] == 'Z' || key[1] == 'z') && len == 2) { + /* Power sensors */ + if (sc->sc_power_count >= ASMC_MAX_SENSORS) + continue; + sensor_key = malloc(ASMC_KEYLEN + 1, + M_DEVBUF, M_WAITOK); + memcpy(sensor_key, key, ASMC_KEYLEN + 1); + sc->sc_power_sensors[sc->sc_power_count++] = + sensor_key; + } else if (key[0] == 'A' && key[1] == 'L' && + (key[2] == 'V' || key[2] == 'S') && len == 2) { + /* Ambient light sensors */ + if (sc->sc_light_count >= ASMC_MAX_SENSORS) + continue; + sensor_key = malloc(ASMC_KEYLEN + 1, + M_DEVBUF, M_WAITOK); + memcpy(sensor_key, key, ASMC_KEYLEN + 1); + sc->sc_light_sensors[sc->sc_light_count++] = + sensor_key; + } + } + + if (bootverbose) + device_printf(dev, + "detected %d voltage, %d current, " + "%d power, %d light sensors\n", + sc->sc_voltage_count, sc->sc_current_count, + sc->sc_power_count, sc->sc_light_count); + + /* Register sysctls for detected sensors */ + sysctlctx = device_get_sysctl_ctx(dev); + + /* Voltage sensors */ + if (sc->sc_voltage_count > 0) { + tree_node = SYSCTL_ADD_NODE(sysctlctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "voltage", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Voltage sensors (millivolts)"); + + for (i = 0; i < sc->sc_voltage_count; i++) { + SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(tree_node), + OID_AUTO, sc->sc_voltage_sensors[i], + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, + dev, ('V' << 8) | i, asmc_sensor_sysctl, "I", + "Voltage sensor (millivolts)"); } - for (i = 0; i < sizeof(v); i++) { - v[i] = 0; + } + + /* Current sensors */ + if (sc->sc_current_count > 0) { + tree_node = SYSCTL_ADD_NODE(sysctlctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "current", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Current sensors (milliamps)"); + + for (i = 0; i < sc->sc_current_count; i++) { + SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(tree_node), + OID_AUTO, sc->sc_current_sensors[i], + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, + dev, ('I' << 8) | i, asmc_sensor_sysctl, "I", + "Current sensor (milliamps)"); } - asmc_key_read(dev, key, v, maxlen); - snprintf(buf, sizeof(buf), "key %d is: %s, type %s " - "(len %d), data", number, key, type, maxlen); - for (i = 0; i < maxlen; i++) { - snprintf(buf2, sizeof(buf2), " %02x", v[i]); - strlcat(buf, buf2, sizeof(buf)); + } + + /* Power sensors */ + if (sc->sc_power_count > 0) { + tree_node = SYSCTL_ADD_NODE(sysctlctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "power", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Power sensors (milliwatts)"); + + for (i = 0; i < sc->sc_power_count; i++) { + SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(tree_node), + OID_AUTO, sc->sc_power_sensors[i], + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, + dev, ('P' << 8) | i, asmc_sensor_sysctl, "I", + "Power sensor (milliwatts)"); + } + } + + /* Ambient light sensors */ + if (sc->sc_light_count > 0) { + tree_node = SYSCTL_ADD_NODE(sysctlctx, + SYSCTL_CHILDREN(device_get_sysctl_tree(dev)), OID_AUTO, + "ambient", CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Ambient light sensors"); + + for (i = 0; i < sc->sc_light_count; i++) { + SYSCTL_ADD_PROC(sysctlctx, SYSCTL_CHILDREN(tree_node), + OID_AUTO, sc->sc_light_sensors[i], + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, + dev, ('L' << 8) | i, asmc_sensor_sysctl, "I", + "Light sensor value"); } - strlcat(buf, " \n", sizeof(buf)); - device_printf(dev, "%s", buf); } + return (0); +} + +/* + * Helper function to get key info by index (for sensor detection). + */ +static int +asmc_key_dump_by_index(device_t dev, int index, char *key_out, + char *type_out, uint8_t *len_out) +{ + struct asmc_softc *sc = device_get_softc(dev); + uint8_t index_buf[ASMC_KEYLEN]; + uint8_t key_buf[ASMC_KEYLEN]; + uint8_t info_buf[ASMC_KEYINFO_RESPLEN]; + int error = ENXIO, try = 0; + int i; + + mtx_lock_spin(&sc->sc_mtx); + + index_buf[0] = (index >> 24) & 0xff; + index_buf[1] = (index >> 16) & 0xff; + index_buf[2] = (index >> 8) & 0xff; + index_buf[3] = index & 0xff; + +begin: + if (asmc_command(dev, ASMC_CMDGETBYINDEX)) + goto out; + + for (i = 0; i < ASMC_KEYLEN; i++) { + ASMC_DATAPORT_WRITE(sc, index_buf[i]); + if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) + goto out; + } + + ASMC_DATAPORT_WRITE(sc, ASMC_KEYLEN); + + for (i = 0; i < ASMC_KEYLEN; i++) { + if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) + goto out; + key_buf[i] = ASMC_DATAPORT_READ(sc); + } + + if (asmc_command(dev, ASMC_CMDGETINFO)) + goto out; + + for (i = 0; i < ASMC_KEYLEN; i++) { + ASMC_DATAPORT_WRITE(sc, key_buf[i]); + if (asmc_wait(dev, ASMC_STATUS_AWAIT_DATA)) + goto out; + } + + ASMC_DATAPORT_WRITE(sc, ASMC_KEYINFO_RESPLEN); + + for (i = 0; i < ASMC_KEYINFO_RESPLEN; i++) { + if (asmc_wait(dev, ASMC_STATUS_DATA_READY)) + goto out; + info_buf[i] = ASMC_DATAPORT_READ(sc); + } + + memcpy(key_out, key_buf, ASMC_KEYLEN); + key_out[ASMC_KEYLEN] = '\0'; + *len_out = info_buf[0]; + memcpy(type_out, &info_buf[1], ASMC_TYPELEN); + type_out[ASMC_TYPELEN] = '\0'; + error = 0; + +out: + if (error) { + if (++try < ASMC_MAXRETRIES) + goto begin; + } + + mtx_unlock_spin(&sc->sc_mtx); return (error); } -#endif static int asmc_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len) @@ -1183,15 +1956,15 @@ begin: error = 0; out: if (error) { - if (++try < 10) goto begin; - device_printf(dev,"%s for key %s failed %d times, giving up\n", - __func__, key, try); + if (++try < 10) + goto begin; + device_printf(dev, "%s for key %s failed %d times, giving up\n", + __func__, key, try); } mtx_unlock_spin(&sc->sc_mtx); return (error); - } /* @@ -1202,7 +1975,7 @@ asmc_fan_count(device_t dev) { uint8_t buf[1]; - if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, sizeof buf) != 0) + if (asmc_key_read(dev, ASMC_KEY_FANCOUNT, buf, sizeof(buf)) != 0) return (-1); return (buf[0]); @@ -1216,23 +1989,24 @@ asmc_fan_getvalue(device_t dev, const char *key, int fan) char fankey[5]; snprintf(fankey, sizeof(fankey), key, fan); - if (asmc_key_read(dev, fankey, buf, sizeof buf) != 0) + if (asmc_key_read(dev, fankey, buf, sizeof(buf)) != 0) return (-1); speed = (buf[0] << 6) | (buf[1] >> 2); return (speed); } -static char* -asmc_fan_getstring(device_t dev, const char *key, int fan, uint8_t *buf, uint8_t buflen) +static char * +asmc_fan_getstring(device_t dev, const char *key, int fan, uint8_t *buf, + uint8_t buflen) { char fankey[5]; - char* desc; + char *desc; snprintf(fankey, sizeof(fankey), key, fan); if (asmc_key_read(dev, fankey, buf, buflen) != 0) return (NULL); - desc = buf+4; + desc = buf + 4; return (desc); } @@ -1245,11 +2019,11 @@ asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed) speed *= 4; - buf[0] = speed>>8; + buf[0] = speed >> 8; buf[1] = speed; snprintf(fankey, sizeof(fankey), key, fan); - if (asmc_key_write(dev, fankey, buf, sizeof buf) < 0) + if (asmc_key_write(dev, fankey, buf, sizeof(buf)) < 0) return (-1); return (0); @@ -1258,7 +2032,7 @@ asmc_fan_setvalue(device_t dev, const char *key, int fan, int speed) static int asmc_mb_sysctl_fanspeed(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; int fan = arg2; int error; int32_t v; @@ -1273,10 +2047,10 @@ static int asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS) { uint8_t buf[16]; - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; int fan = arg2; int error = true; - char* desc; + char *desc; desc = asmc_fan_getstring(dev, ASMC_KEY_FANID, fan, buf, sizeof(buf)); @@ -1289,7 +2063,7 @@ asmc_mb_sysctl_fanid(SYSCTL_HANDLER_ARGS) static int asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; int fan = arg2; int error; int32_t v; @@ -1303,7 +2077,7 @@ asmc_mb_sysctl_fansafespeed(SYSCTL_HANDLER_ARGS) static int asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; int fan = arg2; int error; int32_t v; @@ -1322,7 +2096,7 @@ asmc_mb_sysctl_fanminspeed(SYSCTL_HANDLER_ARGS) static int asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; int fan = arg2; int error; int32_t v; @@ -1341,7 +2115,7 @@ asmc_mb_sysctl_fanmaxspeed(SYSCTL_HANDLER_ARGS) static int asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; int fan = arg2; int error; int32_t v; @@ -1360,7 +2134,7 @@ asmc_mb_sysctl_fantargetspeed(SYSCTL_HANDLER_ARGS) static int asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; int fan = arg2; int error; int32_t v; @@ -1384,7 +2158,8 @@ asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS) if (v != 0 && v != 1) return (EINVAL); /* Read-modify-write of FS! bitmask */ - error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, sizeof(buf)); + error = asmc_key_read(dev, ASMC_KEY_FANMANUAL, buf, + sizeof(buf)); if (error == 0) { val = (buf[0] << 8) | buf[1]; @@ -1397,7 +2172,8 @@ asmc_mb_sysctl_fanmanual(SYSCTL_HANDLER_ARGS) /* Write back */ buf[0] = val >> 8; buf[1] = val & 0xff; - error = asmc_key_write(dev, ASMC_KEY_FANMANUAL, buf, sizeof(buf)); + error = asmc_key_write(dev, ASMC_KEY_FANMANUAL, buf, + sizeof(buf)); } } @@ -1415,7 +2191,7 @@ asmc_temp_getvalue(device_t dev, const char *key) /* * Check for invalid temperatures. */ - if (asmc_key_read(dev, key, buf, sizeof buf) != 0) + if (asmc_key_read(dev, key, buf, sizeof(buf)) != 0) return (-1); return (buf[0]); @@ -1424,7 +2200,7 @@ asmc_temp_getvalue(device_t dev, const char *key) static int asmc_temp_sysctl(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; struct asmc_softc *sc = device_get_softc(dev); int error, val; @@ -1448,12 +2224,12 @@ asmc_sms_read(device_t dev, const char *key, int16_t *val) case 'X': case 'Y': case 'Z': - error = asmc_key_read(dev, key, buf, sizeof buf); + error = asmc_key_read(dev, key, buf, sizeof(buf)); break; default: device_printf(dev, "%s called with invalid argument %s\n", - __func__, key); - error = 1; + __func__, key); + error = EINVAL; goto out; } *val = ((int16_t)buf[0] << 8) | buf[1]; @@ -1475,7 +2251,7 @@ static int asmc_sms_intrfast(void *arg) { uint8_t type; - device_t dev = (device_t) arg; + device_t dev = (device_t)arg; struct asmc_softc *sc = device_get_softc(dev); if (!sc->sc_sms_intr_works) return (FILTER_HANDLED); @@ -1548,13 +2324,13 @@ asmc_sms_task(void *arg, int pending) static int asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; int error; int16_t val; int32_t v; asmc_sms_read(dev, ASMC_KEY_SMS_X, &val); - v = (int32_t) val; + v = (int32_t)val; error = sysctl_handle_int(oidp, &v, 0, req); return (error); @@ -1563,13 +2339,13 @@ asmc_mb_sysctl_sms_x(SYSCTL_HANDLER_ARGS) static int asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; int error; int16_t val; int32_t v; asmc_sms_read(dev, ASMC_KEY_SMS_Y, &val); - v = (int32_t) val; + v = (int32_t)val; error = sysctl_handle_int(oidp, &v, 0, req); return (error); @@ -1578,13 +2354,13 @@ asmc_mb_sysctl_sms_y(SYSCTL_HANDLER_ARGS) static int asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; int error; int16_t val; int32_t v; asmc_sms_read(dev, ASMC_KEY_SMS_Z, &val); - v = (int32_t) val; + v = (int32_t)val; error = sysctl_handle_int(oidp, &v, 0, req); return (error); @@ -1593,12 +2369,12 @@ asmc_mb_sysctl_sms_z(SYSCTL_HANDLER_ARGS) static int asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; uint8_t buf[6]; int error; int32_t v; - asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof buf); + asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf)); v = buf[2]; error = sysctl_handle_int(oidp, &v, 0, req); @@ -1608,12 +2384,12 @@ asmc_mbp_sysctl_light_left(SYSCTL_HANDLER_ARGS) static int asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; uint8_t buf[6]; int error; int32_t v; - asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, sizeof buf); + asmc_key_read(dev, ASMC_KEY_LIGHTRIGHT, buf, sizeof(buf)); v = buf[2]; error = sysctl_handle_int(oidp, &v, 0, req); @@ -1623,7 +2399,8 @@ asmc_mbp_sysctl_light_right(SYSCTL_HANDLER_ARGS) static int asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; + struct asmc_softc *sc = device_get_softc(dev); uint8_t buf[2]; int error; int v; @@ -1635,9 +2412,10 @@ asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS) if (v < 0 || v > 255) return (EINVAL); light_control = v; + sc->sc_kbd_bkl_level = v * 100 / 255; buf[0] = light_control; buf[1] = 0x00; - asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof buf); + asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); } return (error); } @@ -1645,12 +2423,12 @@ asmc_mbp_sysctl_light_control(SYSCTL_HANDLER_ARGS) static int asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS) { - device_t dev = (device_t) arg1; + device_t dev = (device_t)arg1; uint8_t buf[10]; int error; uint32_t v; - asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof buf); + asmc_key_read(dev, ASMC_KEY_LIGHTLEFT, buf, sizeof(buf)); /* * This seems to be a 32 bit big endian value from buf[6] -> buf[9]. @@ -1671,3 +2449,69 @@ asmc_mbp_sysctl_light_left_10byte(SYSCTL_HANDLER_ARGS) return (error); } + +/* + * Wake-on-LAN convenience sysctl. + * Reading returns 1 if WoL is enabled, 0 if disabled. + * Writing 1 enables WoL, 0 disables it. + */ +static int +asmc_wol_sysctl(SYSCTL_HANDLER_ARGS) +{ + device_t dev = (device_t)arg1; + uint8_t aupo; + int val, error; + + /* Read current AUPO value */ + if (asmc_key_read(dev, ASMC_KEY_AUPO, &aupo, 1) != 0) + return (EIO); + + val = (aupo != 0) ? 1 : 0; + error = sysctl_handle_int(oidp, &val, 0, req); + if (error != 0 || req->newptr == NULL) + return (error); + + /* Clamp to 0 or 1 */ + aupo = (val != 0) ? 1 : 0; + + /* Write AUPO */ + if (asmc_key_write(dev, ASMC_KEY_AUPO, &aupo, 1) != 0) + return (EIO); + + return (0); +} + +static int +asmc_backlight_update_status(device_t dev, struct backlight_props *props) +{ + struct asmc_softc *sc = device_get_softc(dev); + uint8_t buf[2]; + + sc->sc_kbd_bkl_level = props->brightness; + light_control = props->brightness * 255 / 100; + buf[0] = light_control; + buf[1] = 0x00; + asmc_key_write(dev, ASMC_KEY_LIGHTVALUE, buf, sizeof(buf)); + + return (0); +} + +static int +asmc_backlight_get_status(device_t dev, struct backlight_props *props) +{ + struct asmc_softc *sc = device_get_softc(dev); + + props->brightness = sc->sc_kbd_bkl_level; + props->nlevels = 0; + + return (0); +} + +static int +asmc_backlight_get_info(device_t dev, struct backlight_info *info) +{ + info->type = BACKLIGHT_TYPE_KEYBOARD; + strlcpy(info->name, "Apple MacBook Keyboard", BACKLIGHTMAXNAMELENGTH); + + return (0); +} diff --git a/sys/dev/asmc/asmcvar.h b/sys/dev/asmc/asmcvar.h index b6d8686d9670..43f679f3fef0 100644 --- a/sys/dev/asmc/asmcvar.h +++ b/sys/dev/asmc/asmcvar.h @@ -28,6 +28,10 @@ */ #define ASMC_MAXFANS 6 +#define ASMC_MAXVAL 32 /* Maximum SMC value size */ +#define ASMC_KEYLEN 4 /* SMC key name length */ +#define ASMC_TYPELEN 4 /* SMC type string length */ +#define ASMC_MAX_SENSORS 64 /* Max sensors per type */ struct asmc_softc { device_t sc_dev; @@ -51,6 +55,25 @@ struct asmc_softc { struct taskqueue *sc_sms_tq; struct task sc_sms_task; uint8_t sc_sms_intr_works; + struct cdev *sc_kbd_bkl; + uint32_t sc_kbd_bkl_level; +#ifdef ASMC_DEBUG + /* Raw key access */ + struct sysctl_oid *sc_raw_tree; + char sc_rawkey[ASMC_KEYLEN + 1]; + uint8_t sc_rawval[ASMC_MAXVAL]; + uint8_t sc_rawlen; + char sc_rawtype[ASMC_TYPELEN + 1]; +#endif + /* Voltage/Current/Power/Light sensors */ + char *sc_voltage_sensors[ASMC_MAX_SENSORS]; + int sc_voltage_count; + char *sc_current_sensors[ASMC_MAX_SENSORS]; + int sc_current_count; + char *sc_power_sensors[ASMC_MAX_SENSORS]; + int sc_power_count; + char *sc_light_sensors[ASMC_MAX_SENSORS]; + int sc_light_count; }; /* @@ -69,6 +92,14 @@ struct asmc_softc { bus_write_1(sc->sc_ioport, 0x04, val) #define ASMC_CMDREAD 0x10 #define ASMC_CMDWRITE 0x11 +#define ASMC_CMDGETBYINDEX 0x12 +#define ASMC_CMDGETINFO 0x13 + +#define ASMC_STATUS_AWAIT_DATA 0x04 +#define ASMC_STATUS_DATA_READY 0x05 + +#define ASMC_KEYINFO_RESPLEN 6 /* getinfo: 1 len + 4 type + 1 attr */ +#define ASMC_MAXRETRIES 10 /* * Interrupt port. @@ -78,6 +109,9 @@ struct asmc_softc { /* Number of keys */ #define ASMC_NKEYS "#KEY" /* RO; 4 bytes */ +/* Query the ASMC revision */ +#define ASMC_KEY_REV "REV " /* RO: 6 bytes */ + /* * Fan control via SMC. */ @@ -85,7 +119,7 @@ struct asmc_softc { #define ASMC_KEY_FANMANUAL "FS! " /* RW; 2 bytes */ #define ASMC_KEY_FANID "F%dID" /* RO; 16 bytes */ #define ASMC_KEY_FANSPEED "F%dAc" /* RO; 2 bytes */ -#define ASMC_KEY_FANMINSPEED "F%dMn" /* RO; 2 bytes */ +#define ASMC_KEY_FANMINSPEED "F%dMn" /* RW; 2 bytes */ #define ASMC_KEY_FANMAXSPEED "F%dMx" /* RO; 2 bytes */ #define ASMC_KEY_FANSAFESPEED "F%dSf" /* RO; 2 bytes */ #define ASMC_KEY_FANTARGETSPEED "F%dTg" /* RW; 2 bytes */ @@ -126,6 +160,11 @@ struct asmc_softc { #define ASMC_KEY_CLAMSHELL "MSLD" /* RO; 1 byte */ /* + * Auto power on / Wake-on-LAN. + */ +#define ASMC_KEY_AUPO "AUPO" /* RW; 1 byte */ + +/* * Interrupt keys. */ #define ASMC_KEY_INTOK "NTOK" /* WO; 1 byte */ @@ -327,6 +366,39 @@ struct asmc_softc { "TMBS", "TP0P", "TPCD", "TW0P", "Th1H", \ "Th2H", "Tm0P", "Ts0P", "Ts0S" } +#define ASMC_MBP83_TEMPS { "ALSL", "F0Ac", "F1Ac", "IB0R", "IC0R", \ + "ID0R", "IG0R", "IO0R", "PCPC", "PCPG", \ + "PCPT", "PD0R", "TB1T", "TB2T", "TC0C", \ + "TC0D", "TC0P", "TC1C", "TC2C", "TC3C", \ + "TC4C", "TG0D", "TG0P", "THSP", "TP0P", \ + "TPCD", "Th1H", "Th2H", "Tm0P", "Ts0P", \ + "VC0C", "VD0R", "VG0C", "VN0C", "VP0R", NULL } + +#define ASMC_MBP83_TEMPNAMES { "ambient_light", "fan_leftside", "fan_rightside", \ + "battery_current", "cpu_vcorevtt", "dc_current", \ + "gpu_voltage", "other", "cpu_package_core", \ + "cpu_package_gpu", "cpu_package_total", "dc_in", \ + "battery_1", "battery_2", "cpu_die_digital", \ + "cpu_die_analog", "cpu_proximity", "cpu_core_1", \ + "cpu_core_2", "cpu_core_3", "cpu_core_4", "gpu_die_analog", \ + "gpu_proximity", "thunderbolt", "platform_controller", \ + "pch_die_digital", "right_fin_stack", "left_fin_stack", \ + "dc_in_air_flow", "palm_rest", "cpu_vcore", "dc_in_voltage", \ + "gpu_vcore", "intel_gpu_vcore", "pbus_voltage" } + +#define ASMC_MBP83_TEMPDESCS { "Ambient Light", "Fan Leftside", "Fan Rightside", \ + "Battery BMON Current", "CPU VcoreVTT", "DC In AMON Current", \ + "GPU Voltage", "Other 5V 3V", "CPU Package Core", \ + "CPU Package GPU", "CPU Package Total", "DC In", \ + "Battery Sensor 1", "Battery Sensor 2", "CPU Die Digital", \ + "CPU Die Analog", "CPU Proximity", "CPU Core 1 DTS", \ + "CPU Core 2 DTS", "CPU Core 3 DTS", "CPU Core 4 DTS", \ + "GPU Die Analog", "GPU Proximity", "Thunderbolt Proximity", \ + "Platform Controller Hub", "PCH Die Digital", \ + "Right Fin Stack Proximity", "Left Fin Stack Proximity", \ + "DC In Proximity Air Flow", "Palm Rest", "CPU VCore", \ + "DC In Voltage", "GPU VCore", "Intel GPU VCore", "PBus Voltage" } + #define ASMC_MBP91_TEMPS { "TA0P", "TB0T", "TB1T", "TB2T", "TC0E", \ "TC0F", "TC0P", "TC1C", "TC2C", "TC3C", \ "TC4C", "TCGC", "TCSA", "TCXC", "TG0D", \ @@ -467,6 +539,59 @@ struct asmc_softc { "Pbus", "Ambient Light", "Leftside", "Rightside", "CPU Package Core", \ "CPU Package GPU", "CPU Package Total", "System Total", "DC In" } +/* MacBookPro11,5 - same as 11,4 but without IBLC, ICMC, and IC2C keys */ +#define ASMC_MBP115_TEMPS { "IC0C", "ID0R", "IHDC", "IPBR", "IC0R", \ + "IO3R", "IO5R", "IM0C", "IC1C", \ + "IC3C", "ILDC", "IAPC", "IHSC", \ + "TC0P", "TP0P", "TM0P", \ + "Ta0P", "Th2H", "Th1H", "TW0P", "Ts0P", \ + "Ts1P", "TB0T", "TB1T", "TB2T", "TH0A", "TH0B", \ + "TC1C", "TC2C", "TC3C", "TC4C", "TCXC", \ + "TCGC", "TPCD", "TCSA", "VC0C", "VD0R", \ + "VP0R", "ALSL", "F0Ac", "F1Ac", "PCPC", \ + "PCPG", "PCPT", "PSTR", "PDTR", NULL } + + +#define ASMC_MBP115_TEMPNAMES { "IC0C", "ID0R", "IHDC", "IPBR", "IC0R", \ + "IO3R", "IO5R", "IM0C", "IC1C", \ + "IC3C", "ILDC", "IAPC", "IHSC", \ + "TC0P", "TP0P", "TM0P", \ + "Ta0P", "Th2H", "Th1H", "TW0P", "Ts0P", \ + "Ts1P", "TB0T", "TB1T", "TB2T", "TH0A", "TH0B", \ + "TC1C", "TC2C", "TC3C", "TC4C", "TCXC", \ + "TCGC", "TPCD", "TCSA", "VC0C", "VD0R", \ + "VP0R", "ALSL", "F0Ac", "F1Ac", "PCPC", \ + "PCPG", "PCPT", "PSTR", "PDTR" } + +#define ASMC_MBP115_TEMPDESCS { "CPU High (CPU, I/O)", "DC In", "SSD", "Charger (BMON)", "CPU", \ + "Other 3.3V", "Other 5V", "Memory", "Platform Controller Hub Core", \ + "CPU DDR", "LCD Panel", "Airport", "Thunderbolt", \ + "CPU Proximity", "Platform Controller Hub", "Memory Proximity", "Air Flow Proximity", \ + "Left Fin Stack", "Right Fin Stack", "Airport Proximity", "Palm Rest", "Palm Rest Actuator", \ + "Battery Max", "Battery Sensor 1", "Battery Sensor 2", "SSD A", "SSD B", \ + "CPU Core 1", "CPU Core 2", "CPU Core 3", "CPU Core 4", "CPU PECI Die", \ + "Intel GPU", "Platform Controller Hub PECI", "CPU System Agent Core", "CPU VCore", "DC In", \ + "Pbus", "Ambient Light", "Leftside", "Rightside", "CPU Package Core", \ + "CPU Package GPU", "CPU Package Total", "System Total", "DC In" } + +#define ASMC_MBP131_TEMPS { "TB0T", "TB1T", "TB2T", "TC0F", \ + "TC0P", "TC1C", "TC2C", "TCGC", \ + "TCSA", "TCXC", "Th1H", "TM0P", \ + "TPCD", "Ts0P", "Ts0S", "TaLC", \ + "Ts1P", NULL } + +#define ASMC_MBP131_TEMPNAMES { "battery", "battery_1", "battery_2", "cpu_die_peci", \ + "cpu_proximity", "cpu_core_1", "cpu_core_2", "intel_gpu", \ + "cpu_sys_agent", "cpu_core_peci", "right_fin_stack", "memory_proximity", \ + "platform_ctrl_hub", "trackpad", "bottom_skin", "air_flow", \ + "trackpad_act" } + +#define ASMC_MBP131_TEMPDESCS { "Battery", "Battery Sensor 1", "Battery Sensor 2", "CPU Die (PECI)", \ + "CPU Proximity", "CPU Core 1", "CPU Core 2", "Intel GPU", \ + "CPU System Agent Core (PECI)", "CPU Core (PECI)", "Right Fin Stack", "DDR3 Proximity", \ + "Platform Controller Hub Die", "Trackpad", "Bottom Skin", "Air Flow", \ + "Trackpad Actuator" } + #define ASMC_MM_TEMPS { "TN0P", "TN1P", NULL } #define ASMC_MM_TEMPNAMES { "northbridge1", "northbridge2" } #define ASMC_MM_TEMPDESCS { "Northbridge Point 1", \ @@ -721,6 +846,75 @@ struct asmc_softc { "Power Supply, Location 2", \ "Tv0S", "Tv1S", } +#define ASMC_MP31_TEMPS { "TA0P", \ + "TC0C", "TC0D", "TC0P", \ + "TC1C", "TC1D", \ + "TC2C", "TC2D", \ + "TC3C", "TC3D", \ + "TCAG", "TCAH", "TCBG", "TCBH", \ + "TH0P", "TH1P", "TH2P", "TH3P", \ + "TM0P", "TM0S", "TM1P", "TM1S", \ + "TM2P", "TM2S", "TM3S", \ + "TM8P", "TM8S", "TM9P", "TM9S", \ + "TMAP", "TMAS", "TMBS", \ + "TN0C", "TN0D", "TN0H", \ + "TS0C", \ + "Tp0C", "Tp1C", \ + "Tv0S", "Tv1S", NULL } + +#define ASMC_MP31_TEMPNAMES { "ambient", \ + "cpu_core0", "cpu_diode0", "cpu_a_proximity", \ + "cpu_core1", "cpu_diode1", \ + "cpu_core2", "cpu_diode2", \ + "cpu_core3", "cpu_diode3", \ + "cpu_a_pkg", "cpu_a_heatsink", \ + "cpu_b_pkg", "cpu_b_heatsink", \ + "hdd_bay0", "hdd_bay1", \ + "hdd_bay2", "hdd_bay3", \ + "mem_riser_a_prox0", "mem_riser_a_slot0", \ + "mem_riser_a_prox1", "mem_riser_a_slot1", \ + "mem_riser_a_prox2", "mem_riser_a_slot2", \ + "mem_riser_a_slot3", \ + "mem_riser_b_prox0", "mem_riser_b_slot0", \ + "mem_riser_b_prox1", "mem_riser_b_slot1", \ + "mem_riser_b_prox2", "mem_riser_b_slot2", \ + "mem_riser_b_slot3", \ + "northbridge_core", "northbridge_diode", \ + "northbridge_heatsink", \ + "expansion_slots", \ + "power_supply0", "power_supply1", \ + "vrm0", "vrm1", } + +#define ASMC_MP31_TEMPDESCS { "Ambient Air", \ + "CPU Core 1", "CPU Diode 1", \ + "CPU A Proximity", \ + "CPU Core 2", "CPU Diode 2", \ + "CPU Core 3", "CPU Diode 3", \ + "CPU Core 4", "CPU Diode 4", \ + "CPU A Package", "CPU A Heatsink", \ + "CPU B Package", "CPU B Heatsink", \ + "Hard Drive Bay 1", "Hard Drive Bay 2", \ + "Hard Drive Bay 3", "Hard Drive Bay 4", \ + "Memory Riser A, Proximity 1", \ + "Memory Riser A, Slot 1", \ + "Memory Riser A, Proximity 2", \ + "Memory Riser A, Slot 2", \ + "Memory Riser A, Proximity 3", \ + "Memory Riser A, Slot 3", \ + "Memory Riser A, Slot 4", \ + "Memory Riser B, Proximity 1", \ + "Memory Riser B, Slot 1", \ + "Memory Riser B, Proximity 2", \ + "Memory Riser B, Slot 2", \ + "Memory Riser B, Proximity 3", \ + "Memory Riser B, Slot 3", \ + "Memory Riser B, Slot 4", \ + "Northbridge Core", "Northbridge Diode", \ + "Northbridge Heatsink", \ + "Expansion Slots", \ + "Power Supply 1", "Power Supply 2", \ + "VRM 1", "VRM 2", } + #define ASMC_MP2_TEMPS { "TA0P", "TCAG", "TCAH", "TCBG", "TCBH", \ "TC0C", "TC0D", "TC0P", "TC1C", "TC1D", \ "TC2C", "TC2D", "TC3C", "TC3D", "THTG", \ diff --git a/sys/dev/ata/ata-lowlevel.c b/sys/dev/ata/ata-lowlevel.c index ac764eaf7d15..c5706d200c1c 100644 --- a/sys/dev/ata/ata-lowlevel.c +++ b/sys/dev/ata/ata-lowlevel.c @@ -812,13 +812,13 @@ ata_pio_read(struct ata_request *request, int length) { struct ata_channel *ch = device_get_softc(request->parent); struct bio *bio; - uint8_t *addr; - vm_offset_t page; + uint8_t *addr, *page; int todo, done, off, moff, resid, size, i; uint8_t buf[2] __aligned(2); todo = min(request->transfersize, length); - page = done = resid = 0; + page = NULL; + done = resid = 0; while (done < todo) { size = todo - done; @@ -837,7 +837,7 @@ ata_pio_read(struct ata_request *request, int length) bio->bio_ma[moff / PAGE_SIZE]); moff %= PAGE_SIZE; size = min(size, PAGE_SIZE - moff); - addr = (void *)(page + moff); + addr = page + moff; } } else panic("ata_pio_read: Unsupported CAM data type %x\n", @@ -877,9 +877,9 @@ ata_pio_read(struct ata_request *request, int length) } else ATA_IDX_INSL_STRM(ch, ATA_DATA, (void*)addr, size / 4); - if (page) { + if (page != NULL) { pmap_quick_remove_page(page); - page = 0; + page = NULL; } done += size; } @@ -898,13 +898,13 @@ ata_pio_write(struct ata_request *request, int length) { struct ata_channel *ch = device_get_softc(request->parent); struct bio *bio; - uint8_t *addr; - vm_offset_t page; + uint8_t *addr, *page; int todo, done, off, moff, resid, size, i; uint8_t buf[2] __aligned(2); todo = min(request->transfersize, length); - page = done = resid = 0; + page = NULL; + done = resid = 0; while (done < todo) { size = todo - done; @@ -923,7 +923,7 @@ ata_pio_write(struct ata_request *request, int length) bio->bio_ma[moff / PAGE_SIZE]); moff %= PAGE_SIZE; size = min(size, PAGE_SIZE - moff); - addr = (void *)(page + moff); + addr = page + moff; } } else panic("ata_pio_write: Unsupported CAM data type %x\n", @@ -962,9 +962,9 @@ ata_pio_write(struct ata_request *request, int length) ATA_IDX_OUTSL_STRM(ch, ATA_DATA, (void*)addr, size / sizeof(int32_t)); - if (page) { + if (page != NULL) { pmap_quick_remove_page(page); - page = 0; + page = NULL; } done += size; } diff --git a/sys/dev/ata/ata-pci.h b/sys/dev/ata/ata-pci.h index 630d0184c820..5ff3e344c411 100644 --- a/sys/dev/ata/ata-pci.h +++ b/sys/dev/ata/ata-pci.h @@ -430,8 +430,8 @@ struct ata_pci_controller { #define ATA_HT1000_S1 0x024b1166 #define ATA_HT1000_S2 0x024a1166 #define ATA_K2 0x02401166 -#define ATA_FRODO4 0x02411166 -#define ATA_FRODO8 0x02421166 +#define ATA_FRODO8 0x02411166 +#define ATA_FRODO4 0x02421166 #define ATA_SILICON_IMAGE_ID 0x1095 #define ATA_SII3114 0x31141095 diff --git a/sys/dev/ath/ath_hal/ar5211/ar5211_reset.c b/sys/dev/ath/ath_hal/ar5211/ar5211_reset.c index fa5293777f02..c5a86ef78edb 100644 --- a/sys/dev/ath/ath_hal/ar5211/ar5211_reset.c +++ b/sys/dev/ath/ath_hal/ar5211/ar5211_reset.c @@ -1800,7 +1800,7 @@ ar5211GetInterpolatedValue(uint16_t target, /* * Look for value being within 0.1 of the search values * however, NDIS can't do float calculations, so multiply everything - * up by EEP_SCALE so can do integer arithmatic + * up by EEP_SCALE so can do integer arithmetic * * INPUT value -value to search for * INPUT pList -ptr to the list to search diff --git a/sys/dev/ath/if_ath_keycache.c b/sys/dev/ath/if_ath_keycache.c index a58625ad2803..2b40a8940674 100644 --- a/sys/dev/ath/if_ath_keycache.c +++ b/sys/dev/ath/if_ath_keycache.c @@ -134,12 +134,16 @@ ath_keyset_tkip(struct ath_softc *sc, const struct ieee80211_key *k, * TX key goes at first index, RX key at the rx index. * The hal handles the MIC keys at index+64. */ - memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_mic)); + memcpy(hk->kv_mic, + ieee80211_crypto_get_key_txmic_data(k), + sizeof(hk->kv_mic)); KEYPRINTF(sc, k->wk_keyix, hk, zerobssid); if (!ath_hal_keyset(ah, k->wk_keyix, hk, zerobssid)) return 0; - memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); + memcpy(hk->kv_mic, + ieee80211_crypto_get_key_rxmic_data(k), + sizeof(hk->kv_mic)); KEYPRINTF(sc, k->wk_keyix+32, hk, mac); /* XXX delete tx key on failure? */ return ath_hal_keyset(ah, k->wk_keyix+32, hk, mac); @@ -149,8 +153,12 @@ ath_keyset_tkip(struct ath_softc *sc, const struct ieee80211_key *k, * slot, just set key at the first index; the hal * will handle the rest. */ - memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, k->wk_txmic, sizeof(hk->kv_txmic)); + memcpy(hk->kv_mic, + ieee80211_crypto_get_key_rxmic_data(k), + sizeof(hk->kv_mic)); + memcpy(hk->kv_txmic, + ieee80211_crypto_get_key_txmic_data(k), + sizeof(hk->kv_txmic)); KEYPRINTF(sc, k->wk_keyix, hk, mac); return ath_hal_keyset(ah, k->wk_keyix, hk, mac); } @@ -160,13 +168,19 @@ ath_keyset_tkip(struct ath_softc *sc, const struct ieee80211_key *k, * NB: must pass MIC key in expected location when * the keycache only holds one MIC key per entry. */ - memcpy(hk->kv_mic, k->wk_txmic, sizeof(hk->kv_txmic)); + memcpy(hk->kv_mic, + ieee80211_crypto_get_key_txmic_data(k), + sizeof(hk->kv_txmic)); } else - memcpy(hk->kv_txmic, k->wk_txmic, sizeof(hk->kv_txmic)); + memcpy(hk->kv_txmic, + ieee80211_crypto_get_key_txmic_data(k), + sizeof(hk->kv_txmic)); KEYPRINTF(sc, k->wk_keyix, hk, mac); return ath_hal_keyset(ah, k->wk_keyix, hk, mac); } else if (k->wk_flags & IEEE80211_KEY_RECV) { - memcpy(hk->kv_mic, k->wk_rxmic, sizeof(hk->kv_mic)); + memcpy(hk->kv_mic, + ieee80211_crypto_get_key_rxmic_data(k), + sizeof(hk->kv_mic)); KEYPRINTF(sc, k->wk_keyix, hk, mac); return ath_hal_keyset(ah, k->wk_keyix, hk, mac); } @@ -210,8 +224,10 @@ ath_keyset(struct ath_softc *sc, struct ieee80211vap *vap, KASSERT(cip->ic_cipher < nitems(ciphermap), ("invalid cipher type %u", cip->ic_cipher)); hk.kv_type = ciphermap[cip->ic_cipher]; - hk.kv_len = k->wk_keylen; - memcpy(hk.kv_val, k->wk_key, k->wk_keylen); + hk.kv_len = ieee80211_crypto_get_key_len(k); + memcpy(hk.kv_val, + ieee80211_crypto_get_key_data(k), + ieee80211_crypto_get_key_len(k)); } else hk.kv_type = HAL_CIPHER_CLR; diff --git a/sys/dev/atkbdc/atkbd_atkbdc.c b/sys/dev/atkbdc/atkbd_atkbdc.c index d5ef9706d7b9..64545ce63ba9 100644 --- a/sys/dev/atkbdc/atkbd_atkbdc.c +++ b/sys/dev/atkbdc/atkbd_atkbdc.c @@ -61,7 +61,7 @@ static device_method_t atkbd_methods[] = { DEVMETHOD(device_probe, atkbdprobe), DEVMETHOD(device_attach, atkbdattach), DEVMETHOD(device_resume, atkbdresume), - { 0, 0 } + DEVMETHOD_END }; static driver_t atkbd_driver = { diff --git a/sys/dev/atkbdc/atkbdc_isa.c b/sys/dev/atkbdc/atkbdc_isa.c index 062c5fc491e8..fe8bbf0c8d75 100644 --- a/sys/dev/atkbdc/atkbdc_isa.c +++ b/sys/dev/atkbdc/atkbdc_isa.c @@ -75,7 +75,7 @@ static device_method_t atkbdc_isa_methods[] = { DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), - { 0, 0 } + DEVMETHOD_END }; static driver_t atkbdc_isa_driver = { diff --git a/sys/dev/atkbdc/atkbdcreg.h b/sys/dev/atkbdc/atkbdcreg.h index dc2194dc69c2..a731d33b8de2 100644 --- a/sys/dev/atkbdc/atkbdcreg.h +++ b/sys/dev/atkbdc/atkbdcreg.h @@ -215,7 +215,7 @@ typedef struct atkbdc_softc { } atkbdc_softc_t; enum kbdc_device_ivar { - KBDC_IVAR_VENDORID, + KBDC_IVAR_VENDORID = BUS_IVARS_PRIVATE, KBDC_IVAR_SERIAL, KBDC_IVAR_LOGICALID, KBDC_IVAR_COMPATID, diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c index d36396df0fa0..a2fc68d0f52a 100644 --- a/sys/dev/atkbdc/psm.c +++ b/sys/dev/atkbdc/psm.c @@ -352,6 +352,8 @@ typedef struct elantechhw { int dptracey; int issemimt; int isclickpad; + int hassmbusnotify; + int has3buttons; int hascrc; int hastrackpoint; int haspressure; @@ -417,7 +419,7 @@ enum { ((pb)->ipacket[0] & 0x0c) == 0x0c && ((pb)->ipacket[3] & 0xce) == 0x0c) #define ELANTECH_PKT_IS_V4(pb, hascrc) ((hascrc) ? \ ((pb)->ipacket[3] & 0x08) == 0x00 : \ - ((pb)->ipacket[0] & 0x0c) == 0x04 && ((pb)->ipacket[3] & 0x1c) == 0x10) + ((pb)->ipacket[0] & 0x08) == 0x00 && ((pb)->ipacket[3] & 0x1c) == 0x10) typedef struct elantechaction { finger_t fingers[ELANTECH_MAX_FINGERS]; @@ -743,7 +745,7 @@ static device_method_t psm_methods[] = { DEVMETHOD(device_attach, psmattach), DEVMETHOD(device_detach, psmdetach), DEVMETHOD(device_resume, psmresume), - { 0, 0 } + DEVMETHOD_END }; static driver_t psm_driver = { @@ -1930,8 +1932,11 @@ psm_register_elantech(device_t dev) evdev_support_key(evdev_a, BTN_TOUCH); evdev_support_nfingers(evdev_a, ELANTECH_MAX_FINGERS); evdev_support_key(evdev_a, BTN_LEFT); - if (!sc->elanhw.isclickpad) + if (!sc->elanhw.isclickpad) { evdev_support_key(evdev_a, BTN_RIGHT); + if (sc->elanhw.has3buttons) + evdev_support_key(evdev_a, BTN_MIDDLE); + } psm_support_abs_bulk(evdev_a, elantech_absinfo); error = evdev_register_mtx(evdev_a, &Giant); @@ -4755,6 +4760,9 @@ proc_elantech(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms, touchpad_button = ((pb->ipacket[0] & 0x01) ? MOUSE_BUTTON1DOWN : 0) | ((pb->ipacket[0] & 0x02) ? MOUSE_BUTTON3DOWN : 0); + if (sc->elanhw.has3buttons) + touchpad_button |= + ((pb->ipacket[0] & 0x04) ? MOUSE_BUTTON2DOWN : 0); } #ifdef EVDEV_SUPPORT @@ -7347,6 +7355,9 @@ enable_elantech(struct psm_softc *sc, enum probearg arg) elanhw.hwversion = hwversion; elanhw.issemimt = hwversion == 2; elanhw.isclickpad = (resp[1] & 0x10) != 0; + elanhw.hassmbusnotify = + icversion == 0x0f && (resp[1] & 0x20) != 0 && resp[2] != 0; + elanhw.has3buttons = elanhw.hassmbusnotify; elanhw.hascrc = (resp[1] & 0x40) != 0; elanhw.haspressure = elanhw.fwversion >= 0x020800; @@ -7532,7 +7543,7 @@ static device_attach_t psmcpnp_attach; static device_method_t psmcpnp_methods[] = { DEVMETHOD(device_probe, psmcpnp_probe), DEVMETHOD(device_attach, psmcpnp_attach), - { 0, 0 } + DEVMETHOD_END }; static driver_t psmcpnp_driver = { diff --git a/sys/dev/axgbe/if_axgbe.c b/sys/dev/axgbe/if_axgbe.c index b35beca9c886..9a6b2a95d6b2 100644 --- a/sys/dev/axgbe/if_axgbe.c +++ b/sys/dev/axgbe/if_axgbe.c @@ -559,7 +559,7 @@ static device_method_t axgbe_methods[] = { DEVMETHOD(device_probe, axgbe_probe), DEVMETHOD(device_attach, axgbe_attach), - { 0, 0 } + DEVMETHOD_END }; DEFINE_CLASS_0(axgbe, axgbe_driver, axgbe_methods, @@ -602,7 +602,7 @@ static device_method_t axgbephy_methods[] = { DEVMETHOD(device_probe, axgbephy_probe), DEVMETHOD(device_attach, axgbephy_attach), - { 0, 0 } + DEVMETHOD_END }; DEFINE_CLASS_0(axgbephy, axgbephy_driver, axgbephy_methods, 0); diff --git a/sys/dev/bce/if_bce.c b/sys/dev/bce/if_bce.c index 6cf39e035ea6..84992af0c6b8 100644 --- a/sys/dev/bce/if_bce.c +++ b/sys/dev/bce/if_bce.c @@ -8861,7 +8861,7 @@ bce_sysctl_nvram_write(SYSCTL_HANDLER_ARGS) bzero(sc->nvram_buf, sc->bce_flash_size); error = SYSCTL_IN(req, sc->nvram_buf, sc->bce_flash_size); - if (error == 0) + if (error != 0) return (error); if (req->newlen == sc->bce_flash_size) diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c index cf3084f9b768..2feb19bff677 100644 --- a/sys/dev/bge/if_bge.c +++ b/sys/dev/bge/if_bge.c @@ -3721,7 +3721,12 @@ bge_attach(device_t dev) if_setgetcounterfn(ifp, bge_get_counter); if_setsendqlen(ifp, BGE_TX_RING_CNT - 1); if_setsendqready(ifp); - if_sethwassist(ifp, sc->bge_csum_features); + /* Initially enable checksum offloading either for all of IPv4, TCP/IPv4 + * and UDP/IPv4, or for none. This avoids problems when the interface + * is added to a bridge. + */ + if (sc->bge_csum_features & CSUM_UDP) + if_sethwassist(ifp, sc->bge_csum_features); if_setcapabilities(ifp, IFCAP_HWCSUM | IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU); if ((sc->bge_flags & (BGE_FLAG_TSO | BGE_FLAG_TSO3)) != 0) { @@ -3732,6 +3737,13 @@ bge_attach(device_t dev) if_setcapabilitiesbit(ifp, IFCAP_VLAN_HWCSUM, 0); #endif if_setcapenable(ifp, if_getcapabilities(ifp)); + /* + * Disable TXCSUM capability initially, if UDP checksum offloading is + * not enabled. This avoids problems when the interface is added to a + * bridge. + */ + if ((sc->bge_csum_features & CSUM_UDP) == 0) + if_setcapenablebit(ifp, 0, IFCAP_TXCSUM); #ifdef DEVICE_POLLING if_setcapabilitiesbit(ifp, IFCAP_POLLING, 0); #endif diff --git a/sys/dev/bhnd/bhnd.h b/sys/dev/bhnd/bhnd.h index 1a29b922d491..3d855e23c7e1 100644 --- a/sys/dev/bhnd/bhnd.h +++ b/sys/dev/bhnd/bhnd.h @@ -60,7 +60,7 @@ * bhnd child instance variables */ enum bhnd_device_vars { - BHND_IVAR_VENDOR, /**< Designer's JEP-106 manufacturer ID. */ + BHND_IVAR_VENDOR = BUS_IVARS_PRIVATE, /**< Designer's JEP-106 manufacturer ID. */ BHND_IVAR_DEVICE, /**< Part number */ BHND_IVAR_HWREV, /**< Core revision */ BHND_IVAR_DEVICE_CLASS, /**< Core class (@sa bhnd_devclass_t) */ diff --git a/sys/dev/bhnd/bhnd_bus_if.m b/sys/dev/bhnd/bhnd_bus_if.m index 6ae56ceeb196..7060f944c99b 100644 --- a/sys/dev/bhnd/bhnd_bus_if.m +++ b/sys/dev/bhnd/bhnd_bus_if.m @@ -533,7 +533,7 @@ METHOD int read_board_info { /** * Notify a bhnd bus that a child was added. * - * This method must be called by concrete bhnd(4) driver impementations + * This method must be called by concrete bhnd(4) driver implementations * after @p child's bus state is fully initialized. * * @param dev The bhnd bus whose child is being added. diff --git a/sys/dev/bnxt/bnxt_en/bnxt.h b/sys/dev/bnxt/bnxt_en/bnxt.h index 0ba7b5723b91..64482a656e9d 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt.h +++ b/sys/dev/bnxt/bnxt_en/bnxt.h @@ -455,6 +455,7 @@ struct bnxt_link_info { uint16_t req_link_speed; uint8_t module_status; struct hwrm_port_phy_qcfg_output phy_qcfg_resp; + uint8_t active_lanes; }; enum bnxt_phy_type { @@ -1167,6 +1168,7 @@ struct bnxt_softc { struct iflib_dma_info def_nq_ring_mem; struct task def_cp_task; int db_size; + int db_offset; int legacy_db_size; struct bnxt_doorbell_ops db_ops; @@ -1249,6 +1251,10 @@ struct bnxt_softc { #define BNXT_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO BIT_ULL(47) #define BNXT_FW_CAP_ENABLE_RDMA_SRIOV BIT_ULL(48) #define BNXT_FW_CAP_RSS_TCAM BIT_ULL(49) + + #define BNXT_FW_CAP_SW_MAX_RESOURCE_LIMITS BIT_ULL(61) + #define BNXT_SW_RES_LMT(bp) ((bp)->fw_cap & BNXT_FW_CAP_SW_MAX_RESOURCE_LIMITS) + uint32_t lpi_tmr_lo; uint32_t lpi_tmr_hi; /* copied from flags and flags2 in hwrm_port_phy_qcaps_output */ @@ -1264,6 +1270,7 @@ struct bnxt_softc { #define BNXT_PHY_FL_NO_PAUSE (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_PAUSE_UNSUPPORTED << 8) #define BNXT_PHY_FL_NO_PFC (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_PFC_UNSUPPORTED << 8) #define BNXT_PHY_FL_BANK_SEL (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_BANK_ADDR_SUPPORTED << 8) +#define BNXT_PHY_FL_SPEEDS2 (HWRM_PORT_PHY_QCAPS_OUTPUT_FLAGS2_SPEEDS2_SUPPORTED << 8) struct bnxt_aux_dev *aux_dev; struct net_device *net_dev; struct mtx en_ops_lock; @@ -1333,6 +1340,7 @@ struct bnxt_softc { unsigned long fw_reset_timestamp; struct bnxt_fw_health *fw_health; + char board_partno[64]; }; struct bnxt_filter_info { diff --git a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c index 9e7f4614d9f9..2a79b418fe62 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_hwrm.c @@ -1218,6 +1218,9 @@ bnxt_hwrm_func_qcaps(struct bnxt_softc *softc) flags_ext & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT_DBR_PACING_SUPPORTED) softc->fw_cap |= BNXT_FW_CAP_DBR_PACING_SUPPORTED; + if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_SW_MAX_RESOURCE_LIMITS_SUPPORTED) + softc->fw_cap |= BNXT_FW_CAP_SW_MAX_RESOURCE_LIMITS; + if (flags_ext2 & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_EXT2_GENERIC_STATS_SUPPORTED) softc->fw_cap |= BNXT_FW_CAP_GENERIC_STATS; func->fw_fid = le16toh(resp->fid); @@ -1309,6 +1312,7 @@ bnxt_hwrm_func_qcfg(struct bnxt_softc *softc) goto end; softc->legacy_db_size = le16_to_cpu(resp->legacy_l2_db_size_kb) * 1024; + softc->db_offset = le16toh(resp->legacy_l2_db_size_kb) * 1024; if (BNXT_CHIP_P5(softc)) { if (BNXT_PF(softc)) @@ -1316,6 +1320,7 @@ bnxt_hwrm_func_qcfg(struct bnxt_softc *softc) else min_db_offset = DB_VF_OFFSET_P5; softc->legacy_db_size = min_db_offset; + softc->db_offset = min_db_offset; } softc->db_size = roundup2(le16_to_cpu(resp->l2_doorbell_bar_size_kb) * @@ -2912,10 +2917,14 @@ bnxt_hwrm_port_phy_qcfg(struct bnxt_softc *softc) } link_info->duplex_setting = resp->duplex_cfg; - if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) + if (link_info->phy_link_status == HWRM_PORT_PHY_QCFG_OUTPUT_LINK_LINK) { link_info->link_speed = le16toh(resp->link_speed); - else + if (softc->phy_flags & BNXT_PHY_FL_SPEEDS2) + link_info->active_lanes = resp->active_lanes; + } else { link_info->link_speed = 0; + link_info->active_lanes = 0; + } link_info->force_link_speed = le16toh(resp->force_link_speed); link_info->auto_link_speeds = le16toh(resp->auto_link_speed); link_info->support_speeds = le16toh(resp->support_speeds); diff --git a/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c index bbc12b96d8c6..98ae9848c42b 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.c @@ -387,15 +387,18 @@ bnxt_mgmt_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, int ret = 0; switch(cmd) { - case BNXT_MGMT_OPCODE_GET_DEV_INFO: + case IO_BNXT_MGMT_OPCODE_GET_DEV_INFO: + case IOW_BNXT_MGMT_OPCODE_GET_DEV_INFO: ret = bnxt_mgmt_get_dev_info(dev, cmd, data, flag, td); break; - case BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM: + case IO_BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM: + case IOW_BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM: mtx_lock(&mgmt_lock); ret = bnxt_mgmt_process_hwrm(dev, cmd, data, flag, td); mtx_unlock(&mgmt_lock); break; - case BNXT_MGMT_OPCODE_DCB_OPS: + case IO_BNXT_MGMT_OPCODE_DCB_OPS: + case IOW_BNXT_MGMT_OPCODE_DCB_OPS: ret = bnxt_mgmt_process_dcb(dev, cmd, data, flag, td); break; default: diff --git a/sys/dev/bnxt/bnxt_en/bnxt_mgmt.h b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.h index 8489a223adef..5b94184b1646 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_mgmt.h +++ b/sys/dev/bnxt/bnxt_en/bnxt_mgmt.h @@ -39,9 +39,14 @@ #define DRIVER_NAME "if_bnxt" -#define BNXT_MGMT_OPCODE_GET_DEV_INFO 0x80000000 -#define BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM 0x80000001 -#define BNXT_MGMT_OPCODE_DCB_OPS 0x80000002 + +#define IOW_BNXT_MGMT_OPCODE_GET_DEV_INFO _IOW(0, 0, 0) +#define IOW_BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM _IOW(0, 1, 0) +#define IOW_BNXT_MGMT_OPCODE_DCB_OPS _IOW(0, 2, 0) + +#define IO_BNXT_MGMT_OPCODE_GET_DEV_INFO _IO(0, 0) +#define IO_BNXT_MGMT_OPCODE_PASSTHROUGH_HWRM _IO(0, 1) +#define IO_BNXT_MGMT_OPCODE_DCB_OPS _IO(0, 2) #define BNXT_MGMT_MAX_HWRM_REQ_LENGTH HWRM_MAX_REQ_LEN #define BNXT_MGMT_MAX_HWRM_RESP_LENGTH (512) diff --git a/sys/dev/bnxt/bnxt_en/bnxt_txrx.c b/sys/dev/bnxt/bnxt_en/bnxt_txrx.c index 2e10de6f0174..3e867454de8a 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_txrx.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_txrx.c @@ -154,12 +154,22 @@ bnxt_isc_txd_encap(void *sc, if_pkt_info_t pi) lflags |= TX_BD_LONG_LFLAGS_LSO | TX_BD_LONG_LFLAGS_T_IPID; } - else if(pi->ipi_csum_flags & CSUM_OFFLOAD) { - lflags |= TX_BD_LONG_LFLAGS_TCP_UDP_CHKSUM | - TX_BD_LONG_LFLAGS_IP_CHKSUM; - } - else if(pi->ipi_csum_flags & CSUM_IP) { - lflags |= TX_BD_LONG_LFLAGS_IP_CHKSUM; + else { + if (pi->ipi_csum_flags & CSUM_IP) { + lflags |= TX_BD_LONG_LFLAGS_IP_CHKSUM; + } + switch (pi->ipi_ipproto) { + case IPPROTO_TCP: + if (pi->ipi_csum_flags & (CSUM_IP_TCP | CSUM_IP6_TCP)) { + lflags |= TX_BD_LONG_LFLAGS_TCP_UDP_CHKSUM; + } + break; + case IPPROTO_UDP: + if (pi->ipi_csum_flags & (CSUM_IP_UDP | CSUM_IP6_UDP)) { + lflags |= TX_BD_LONG_LFLAGS_TCP_UDP_CHKSUM; + } + break; + } } tbdh->lflags = htole16(lflags); } diff --git a/sys/dev/bnxt/bnxt_en/bnxt_ulp.c b/sys/dev/bnxt/bnxt_en/bnxt_ulp.c index 3c1f62cb4da3..c6d862a36a9a 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_ulp.c +++ b/sys/dev/bnxt/bnxt_en/bnxt_ulp.c @@ -125,7 +125,7 @@ static void bnxt_fill_msix_vecs(struct bnxt_softc *bp, struct bnxt_msix_entry *e ent[i].vector = bp->irq_tbl[idx + i].vector; ent[i].ring_idx = idx + i; if (BNXT_CHIP_P5_PLUS(bp)) - ent[i].db_offset = DB_PF_OFFSET_P5; + ent[i].db_offset = bp->db_offset; else ent[i].db_offset = (idx + i) * 0x80; @@ -449,6 +449,7 @@ static inline void bnxt_set_edev_info(struct bnxt_en_dev *edev, struct bnxt_soft edev->pdev = bp->pdev; edev->softc = bp; edev->l2_db_size = bp->db_size; + edev->l2_db_offset = bp->db_offset; mtx_init(&bp->en_ops_lock, "Ethernet ops lock", NULL, MTX_DEF); if (bp->flags & BNXT_FLAG_ROCEV1_CAP) @@ -457,9 +458,12 @@ static inline void bnxt_set_edev_info(struct bnxt_en_dev *edev, struct bnxt_soft edev->flags |= BNXT_EN_FLAG_ROCEV2_CAP; if (bp->is_asym_q) edev->flags |= BNXT_EN_FLAG_ASYM_Q; + if (BNXT_SW_RES_LMT(bp)) + edev->flags |= BNXT_EN_FLAG_SW_RES_LMT; edev->hwrm_bar = bp->hwrm_bar; edev->port_partition_type = bp->port_partition_type; edev->ulp_version = BNXT_ULP_VERSION; + memcpy(edev->board_part_number, bp->board_partno, BNXT_VPD_PN_FLD_LEN - 1); } int bnxt_rdma_aux_device_del(struct bnxt_softc *softc) diff --git a/sys/dev/bnxt/bnxt_en/bnxt_ulp.h b/sys/dev/bnxt/bnxt_en/bnxt_ulp.h index 0108293046d7..53bb51b07135 100644 --- a/sys/dev/bnxt/bnxt_en/bnxt_ulp.h +++ b/sys/dev/bnxt/bnxt_en/bnxt_ulp.h @@ -90,10 +90,15 @@ struct bnxt_en_dev { #define BNXT_EN_FLAG_ULP_STOPPED 0x8 #define BNXT_EN_FLAG_ASYM_Q 0x10 #define BNXT_EN_FLAG_MULTI_HOST 0x20 + #define BNXT_EN_FLAG_SW_RES_LMT 0x400 #define BNXT_EN_ASYM_Q(edev) ((edev)->flags & BNXT_EN_FLAG_ASYM_Q) #define BNXT_EN_MH(edev) ((edev)->flags & BNXT_EN_FLAG_MULTI_HOST) +#define BNXT_EN_SW_RES_LMT(edev) ((edev)->flags & BNXT_EN_FLAG_SW_RES_LMT) const struct bnxt_en_ops *en_ops; struct bnxt_ulp ulp_tbl[BNXT_MAX_ULP]; + int l2_db_offset; /* Doorbell BAR offset + * of non-cacheable. + */ int l2_db_size; /* Doorbell BAR size in * bytes mapped by L2 * driver. @@ -121,6 +126,9 @@ struct bnxt_en_dev { struct bnxt_dbr *en_dbr; struct bnxt_bar_info hwrm_bar; u32 espeed; + uint8_t lanes; + #define BNXT_VPD_PN_FLD_LEN 32 + char board_part_number[BNXT_VPD_PN_FLD_LEN]; }; struct bnxt_en_ops { diff --git a/sys/dev/bnxt/bnxt_en/if_bnxt.c b/sys/dev/bnxt/bnxt_en/if_bnxt.c index 471e26a4b252..dea6fd68181e 100644 --- a/sys/dev/bnxt/bnxt_en/if_bnxt.c +++ b/sys/dev/bnxt/bnxt_en/if_bnxt.c @@ -1198,8 +1198,13 @@ static int bnxt_alloc_ctx_mem(struct bnxt_softc *softc) max_srqs = ctxm->max_entries; if (softc->flags & BNXT_FLAG_ROCE_CAP) { pg_lvl = 2; - extra_qps = min_t(u32, 65536, max_qps - l2_qps - qp1_qps); - extra_srqs = min_t(u32, 8192, max_srqs - srqs); + if (BNXT_SW_RES_LMT(softc)) { + extra_qps = max_qps - l2_qps - qp1_qps; + extra_srqs = max_srqs - srqs; + } else { + extra_qps = min_t(uint32_t, 65536, max_qps - l2_qps - qp1_qps); + extra_srqs = min_t(uint32_t, 8192, max_srqs - srqs); + } } ctxm = &ctx->ctx_arr[BNXT_CTX_QP]; @@ -2669,6 +2674,13 @@ bnxt_attach_pre(if_ctx_t ctx) softc->state_bv = bit_alloc(BNXT_STATE_MAX, M_DEVBUF, M_WAITOK|M_ZERO); + if (BNXT_PF(softc)) { + const char *part_num; + + if (pci_get_vpd_readonly(softc->dev, "PN", &part_num) == 0) + snprintf(softc->board_partno, sizeof(softc->board_partno), "%s", part_num); + } + return (rc); failed: @@ -3280,11 +3292,10 @@ bnxt_media_status(if_ctx_t ctx, struct ifmediareq * ifmr) ifmr->ifm_status = IFM_AVALID; ifmr->ifm_active = IFM_ETHER; - if (link_info->link_up) - ifmr->ifm_status |= IFM_ACTIVE; - else - ifmr->ifm_status &= ~IFM_ACTIVE; + if (!link_info->link_up) + return; + ifmr->ifm_status |= IFM_ACTIVE; if (link_info->duplex == HWRM_PORT_PHY_QCFG_OUTPUT_DUPLEX_CFG_FULL) ifmr->ifm_active |= IFM_FDX; else @@ -4295,7 +4306,7 @@ bnxt_i2c_req(if_ctx_t ctx, struct ifi2creq *i2c) return -EOPNOTSUPP; - rc = bnxt_read_sfp_module_eeprom_info(softc, I2C_DEV_ADDR_A0, 0, 0, 0, + rc = bnxt_read_sfp_module_eeprom_info(softc, i2c->dev_addr, 0, 0, 0, i2c->offset, i2c->len, data); return rc; @@ -4790,9 +4801,11 @@ bnxt_report_link(struct bnxt_softc *softc) const char *duplex = NULL, *flow_ctrl = NULL; const char *signal_mode = ""; - if(softc->edev) + if(softc->edev) { softc->edev->espeed = bnxt_fw_to_ethtool_speed(link_info->link_speed); + softc->edev->lanes = link_info->active_lanes; + } if (link_info->link_up == link_info->last_link_up) { if (!link_info->link_up) diff --git a/sys/dev/bnxt/bnxt_re/bnxt_re-abi.h b/sys/dev/bnxt/bnxt_re/bnxt_re-abi.h index 8f48609e7f6f..c7ca19f29046 100644 --- a/sys/dev/bnxt/bnxt_re/bnxt_re-abi.h +++ b/sys/dev/bnxt/bnxt_re/bnxt_re-abi.h @@ -34,7 +34,7 @@ #include <asm/types.h> #include <linux/types.h> -#define BNXT_RE_ABI_VERSION 6 +#define BNXT_RE_ABI_VERSION 7 enum { BNXT_RE_COMP_MASK_UCNTX_WC_DPI_ENABLED = 0x01, @@ -43,12 +43,14 @@ enum { BNXT_RE_COMP_MASK_UCNTX_MQP_EX_SUPPORTED = 0x08, BNXT_RE_COMP_MASK_UCNTX_DBR_PACING_ENABLED = 0x10, BNXT_RE_COMP_MASK_UCNTX_DBR_RECOVERY_ENABLED = 0x20, - BNXT_RE_COMP_MASK_UCNTX_HW_RETX_ENABLED = 0x40 + BNXT_RE_COMP_MASK_UCNTX_HW_RETX_ENABLED = 0x40, + BNXT_RE_COMP_MASK_UCNTX_CMASK_HAVE_MODE = 0x80, }; enum { BNXT_RE_COMP_MASK_REQ_UCNTX_POW2_SUPPORT = 0x01, - BNXT_RE_COMP_MASK_REQ_UCNTX_RSVD_WQE = 0x02 + BNXT_RE_COMP_MASK_REQ_UCNTX_RSVD_WQE = 0x02, + BNXT_RE_COMP_MASK_REQ_UCNTX_VAR_WQE_SUPPORT = 0x03 }; struct bnxt_re_uctx_req { @@ -66,7 +68,7 @@ struct bnxt_re_uctx_resp { __u32 max_cqd; __u32 chip_id0; __u32 chip_id1; - __u32 modes; + __u32 mode; __aligned_u64 comp_mask; } __attribute__((packed)); @@ -134,6 +136,8 @@ struct bnxt_re_qp_req { __u64 qpsva; __u64 qprva; __u64 qp_handle; + __u64 comp_mask; + __u32 sq_slots; } __attribute__((packed)); struct bnxt_re_qp_resp { diff --git a/sys/dev/bnxt/bnxt_re/bnxt_re.h b/sys/dev/bnxt/bnxt_re/bnxt_re.h index fe7a27f4e216..0afc8566c020 100644 --- a/sys/dev/bnxt/bnxt_re/bnxt_re.h +++ b/sys/dev/bnxt/bnxt_re/bnxt_re.h @@ -535,6 +535,7 @@ struct bnxt_re_dev { bool is_virtfn; u32 num_vfs; u32 espeed; + u8 lanes; /* * For storing the speed of slave interfaces. * Same as espeed when bond is not configured @@ -716,7 +717,7 @@ void bnxt_re_remove_device(struct bnxt_re_dev *rdev, u8 removal_type, void bnxt_re_destroy_lag(struct bnxt_re_dev **rdev); int bnxt_re_add_device(struct bnxt_re_dev **rdev, struct ifnet *netdev, - u8 qp_mode, u8 op_type, u8 wqe_mode, u32 num_msix_requested, + u8 qp_mode, u8 op_type, u32 num_msix_requested, struct auxiliary_device *aux_dev); void bnxt_re_create_base_interface(bool primary); int bnxt_re_schedule_work(struct bnxt_re_dev *rdev, unsigned long event, @@ -1069,6 +1070,15 @@ static inline void bnxt_re_set_def_do_pacing(struct bnxt_re_dev *rdev) rdev->qplib_res.pacing_data->do_pacing = rdev->dbr_def_do_pacing; } +static inline bool bnxt_re_is_var_size_supported(struct bnxt_re_dev *rdev, + struct bnxt_re_ucontext *uctx) +{ + if (uctx) + return uctx->cmask & BNXT_RE_UCNTX_CAP_VAR_WQE_ENABLED; + else + return rdev->chip_ctx->modes.wqe_mode; +} + static inline void bnxt_re_set_pacing_dev_state(struct bnxt_re_dev *rdev) { rdev->qplib_res.pacing_data->dev_err_state = diff --git a/sys/dev/bnxt/bnxt_re/ib_verbs.c b/sys/dev/bnxt/bnxt_re/ib_verbs.c index 0383a16757aa..32899abab9ff 100644 --- a/sys/dev/bnxt/bnxt_re/ib_verbs.c +++ b/sys/dev/bnxt/bnxt_re/ib_verbs.c @@ -241,46 +241,99 @@ int bnxt_re_modify_device(struct ib_device *ibdev, return 0; } -static void __to_ib_speed_width(u32 espeed, u8 *speed, u8 *width) +static void __to_ib_speed_width(u32 espeed, u8 lanes, u8 *speed, u8 *width) { - switch (espeed) { - case SPEED_1000: - *speed = IB_SPEED_SDR; + if (!lanes) { + switch (espeed) { + case SPEED_1000: + *speed = IB_SPEED_SDR; + *width = IB_WIDTH_1X; + break; + case SPEED_10000: + *speed = IB_SPEED_QDR; + *width = IB_WIDTH_1X; + break; + case SPEED_20000: + *speed = IB_SPEED_DDR; + *width = IB_WIDTH_4X; + break; + case SPEED_25000: + *speed = IB_SPEED_EDR; + *width = IB_WIDTH_1X; + break; + case SPEED_40000: + *speed = IB_SPEED_QDR; + *width = IB_WIDTH_4X; + break; + case SPEED_50000: + *speed = IB_SPEED_EDR; + *width = IB_WIDTH_2X; + break; + case SPEED_100000: + *speed = IB_SPEED_EDR; + *width = IB_WIDTH_4X; + break; + case SPEED_200000: + *speed = IB_SPEED_HDR; + *width = IB_WIDTH_4X; + break; + case SPEED_400000: + *speed = IB_SPEED_NDR; + *width = IB_WIDTH_4X; + break; + default: + *speed = IB_SPEED_SDR; + *width = IB_WIDTH_1X; + break; + } + return; + } + + switch (lanes) { + case 1: *width = IB_WIDTH_1X; break; - case SPEED_10000: - *speed = IB_SPEED_QDR; - *width = IB_WIDTH_1X; + case 2: + *width = IB_WIDTH_2X; break; - case SPEED_20000: - *speed = IB_SPEED_DDR; + case 4: *width = IB_WIDTH_4X; break; - case SPEED_25000: - *speed = IB_SPEED_EDR; + case 8: + *width = IB_WIDTH_8X; + break; + case 12: + *width = IB_WIDTH_12X; + break; + default: *width = IB_WIDTH_1X; + } + + switch (espeed / lanes) { + case SPEED_2500: + *speed = IB_SPEED_SDR; break; - case SPEED_40000: - *speed = IB_SPEED_QDR; - *width = IB_WIDTH_4X; + case SPEED_5000: + *speed = IB_SPEED_DDR; break; - case SPEED_50000: - *speed = IB_SPEED_EDR; - *width = IB_WIDTH_2X; + case SPEED_10000: + *speed = IB_SPEED_FDR10; break; - case SPEED_100000: + case SPEED_14000: + *speed = IB_SPEED_FDR; + break; + case SPEED_25000: *speed = IB_SPEED_EDR; - *width = IB_WIDTH_4X; break; - case SPEED_200000: + case SPEED_50000: *speed = IB_SPEED_HDR; - *width = IB_WIDTH_4X; + break; + case SPEED_100000: + *speed = IB_SPEED_NDR; break; default: *speed = IB_SPEED_SDR; - *width = IB_WIDTH_1X; - break; - } + } } /* Port */ @@ -318,9 +371,10 @@ int bnxt_re_query_port(struct ib_device *ibdev, u8 port_num, port_attr->subnet_timeout = 0; port_attr->init_type_reply = 0; rdev->espeed = rdev->en_dev->espeed; + rdev->lanes = rdev->en_dev->lanes; if (test_bit(BNXT_RE_FLAG_IBDEV_REGISTERED, &rdev->flags)) - __to_ib_speed_width(rdev->espeed, &active_speed, + __to_ib_speed_width(rdev->espeed, rdev->lanes, &active_speed, &active_width); port_attr->active_speed = active_speed; @@ -1613,15 +1667,18 @@ static int bnxt_re_setup_swqe_size(struct bnxt_re_qp *qp, align = sizeof(struct sq_send_hdr); ilsize = ALIGN(init_attr->cap.max_inline_data, align); - sq->wqe_size = bnxt_re_get_swqe_size(ilsize, sq->max_sge); - if (sq->wqe_size > _get_swqe_sz(dev_attr->max_qp_sges)) - return -EINVAL; - /* For Cu/Wh and gen p5 backward compatibility mode - * wqe size is fixed to 128 bytes + /* For gen p4 and gen p5 fixed wqe compatibility mode + * wqe size is fixed to 128 bytes - ie 6 SGEs */ - if (sq->wqe_size < _get_swqe_sz(dev_attr->max_qp_sges) && - qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) - sq->wqe_size = _get_swqe_sz(dev_attr->max_qp_sges); + if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) { + sq->wqe_size = _get_swqe_sz(BNXT_STATIC_MAX_SGE); + sq->max_sge = BNXT_STATIC_MAX_SGE; + } else { + sq->wqe_size = bnxt_re_get_swqe_size(ilsize, sq->max_sge); + if (sq->wqe_size > _get_swqe_sz(dev_attr->max_qp_sges)) + return -EINVAL; + } + if (init_attr->cap.max_inline_data) { qplqp->max_inline_data = sq->wqe_size - @@ -1666,23 +1723,28 @@ static int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, return rc; bytes = (qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size); + bytes = PAGE_ALIGN(bytes); /* Consider mapping PSN search memory only for RC QPs. */ if (qplib_qp->type == CMDQ_CREATE_QP_TYPE_RC) { psn_sz = _is_chip_gen_p5_p7(rdev->chip_ctx) ? sizeof(struct sq_psn_search_ext) : sizeof(struct sq_psn_search); - if (rdev->dev_attr && BNXT_RE_HW_RETX(rdev->dev_attr->dev_cap_flags)) + if (rdev->dev_attr && _is_host_msn_table(rdev->dev_attr->dev_cap_ext_flags2)) psn_sz = sizeof(struct sq_msn_search); - psn_nume = (qplib_qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? - qplib_qp->sq.max_wqe : - ((qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size) / - sizeof(struct bnxt_qplib_sge)); - if (BNXT_RE_HW_RETX(rdev->dev_attr->dev_cap_flags)) + if (cntx && bnxt_re_is_var_size_supported(rdev, cntx)) { + psn_nume = ureq.sq_slots; + } else { + psn_nume = (qplib_qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? + qplib_qp->sq.max_wqe : + ((qplib_qp->sq.max_wqe * qplib_qp->sq.wqe_size) / + sizeof(struct bnxt_qplib_sge)); + } + if (rdev->dev_attr && _is_host_msn_table(rdev->dev_attr->dev_cap_ext_flags2)) psn_nume = roundup_pow_of_two(psn_nume); bytes += (psn_nume * psn_sz); + bytes = PAGE_ALIGN(bytes); } - bytes = PAGE_ALIGN(bytes); umem = ib_umem_get_compat(rdev, context, udata, ureq.qpsva, bytes, IB_ACCESS_LOCAL_WRITE, 1); if (IS_ERR(umem)) { @@ -1857,6 +1919,7 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp(struct bnxt_re_pd *pd, /* Shadow QP SQ depth should be same as QP1 RQ depth */ qp->qplib_qp.sq.wqe_size = bnxt_re_get_swqe_size(0, 6); qp->qplib_qp.sq.max_wqe = qp1_qp->rq.max_wqe; + qp->qplib_qp.sq.max_sw_wqe = qp1_qp->rq.max_wqe; qp->qplib_qp.sq.max_sge = 2; /* Q full delta can be 1 since it is internal QP */ qp->qplib_qp.sq.q_full_delta = 1; @@ -1868,6 +1931,7 @@ static struct bnxt_re_qp *bnxt_re_create_shadow_qp(struct bnxt_re_pd *pd, qp->qplib_qp.rq.wqe_size = _max_rwqe_sz(6); /* 128 Byte wqe size */ qp->qplib_qp.rq.max_wqe = qp1_qp->rq.max_wqe; + qp->qplib_qp.rq.max_sw_wqe = qp1_qp->rq.max_wqe; qp->qplib_qp.rq.max_sge = qp1_qp->rq.max_sge; qp->qplib_qp.rq.sginfo.pgsize = PAGE_SIZE; qp->qplib_qp.rq.sginfo.pgshft = PAGE_SHIFT; @@ -1940,6 +2004,7 @@ static int bnxt_re_init_rq_attr(struct bnxt_re_qp *qp, entries = init_attr->cap.max_recv_wr + 1; entries = bnxt_re_init_depth(entries, cntx); rq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + 1); + rq->max_sw_wqe = rq->max_wqe; rq->q_full_delta = 0; rq->sginfo.pgsize = PAGE_SIZE; rq->sginfo.pgshft = PAGE_SHIFT; @@ -1964,10 +2029,11 @@ static void bnxt_re_adjust_gsi_rq_attr(struct bnxt_re_qp *qp) static int bnxt_re_init_sq_attr(struct bnxt_re_qp *qp, struct ib_qp_init_attr *init_attr, - void *cntx) + void *cntx, struct ib_udata *udata) { struct bnxt_qplib_dev_attr *dev_attr; struct bnxt_qplib_qp *qplqp; + struct bnxt_re_qp_req ureq; struct bnxt_re_dev *rdev; struct bnxt_qplib_q *sq; int diff = 0; @@ -1979,35 +2045,53 @@ static int bnxt_re_init_sq_attr(struct bnxt_re_qp *qp, sq = &qplqp->sq; dev_attr = rdev->dev_attr; - sq->max_sge = init_attr->cap.max_send_sge; - if (sq->max_sge > dev_attr->max_qp_sges) { - sq->max_sge = dev_attr->max_qp_sges; - init_attr->cap.max_send_sge = sq->max_sge; + if (udata) { + rc = ib_copy_from_udata(&ureq, udata, + min(udata->inlen, sizeof(ureq))); + if (rc) + return -EINVAL; } - rc = bnxt_re_setup_swqe_size(qp, init_attr); - if (rc) - return rc; - /* - * Change the SQ depth if user has requested minimum using - * configfs. Only supported for kernel consumers. Setting - * min_tx_depth to 4096 to handle iser SQ full condition - * in most of the newer OS distros - */ + + sq->max_sge = init_attr->cap.max_send_sge; entries = init_attr->cap.max_send_wr; - if (!cntx && rdev->min_tx_depth && init_attr->qp_type != IB_QPT_GSI) { + if (cntx && udata && qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) { + sq->max_wqe = ureq.sq_slots; + sq->max_sw_wqe = ureq.sq_slots; + sq->wqe_size = sizeof(struct sq_sge); + } else { + if (sq->max_sge > dev_attr->max_qp_sges) { + sq->max_sge = dev_attr->max_qp_sges; + init_attr->cap.max_send_sge = sq->max_sge; + } + rc = bnxt_re_setup_swqe_size(qp, init_attr); + if (rc) + return rc; /* - * If users specify any value greater than 1 use min_tx_depth - * provided by user for comparison. Else, compare it with the - * BNXT_RE_MIN_KERNEL_QP_TX_DEPTH and adjust it accordingly. + * Change the SQ depth if user has requested minimum using + * configfs. Only supported for kernel consumers. Setting + * min_tx_depth to 4096 to handle iser SQ full condition + * in most of the newer OS distros */ - if (rdev->min_tx_depth > 1 && entries < rdev->min_tx_depth) - entries = rdev->min_tx_depth; - else if (entries < BNXT_RE_MIN_KERNEL_QP_TX_DEPTH) - entries = BNXT_RE_MIN_KERNEL_QP_TX_DEPTH; - } - diff = bnxt_re_get_diff(cntx, rdev->chip_ctx); - entries = bnxt_re_init_depth(entries + diff + 1, cntx); - sq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + diff + 1); + + if (!cntx && rdev->min_tx_depth && init_attr->qp_type != IB_QPT_GSI) { + /* + * If users specify any value greater than 1 use min_tx_depth + * provided by user for comparison. Else, compare it with the + * BNXT_RE_MIN_KERNEL_QP_TX_DEPTH and adjust it accordingly. + */ + if (rdev->min_tx_depth > 1 && entries < rdev->min_tx_depth) + entries = rdev->min_tx_depth; + else if (entries < BNXT_RE_MIN_KERNEL_QP_TX_DEPTH) + entries = BNXT_RE_MIN_KERNEL_QP_TX_DEPTH; + } + diff = bnxt_re_get_diff(cntx, rdev->chip_ctx); + entries = bnxt_re_init_depth(entries + diff + 1, cntx); + sq->max_wqe = min_t(u32, entries, dev_attr->max_qp_wqes + diff + 1); + if (qplqp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) + sq->max_sw_wqe = bnxt_qplib_get_depth(sq, qplqp->wqe_mode, true); + else + sq->max_sw_wqe = sq->max_wqe; + } sq->q_full_delta = diff + 1; /* * Reserving one slot for Phantom WQE. Application can @@ -2073,11 +2157,6 @@ out: return qptype; } -static int bnxt_re_init_qp_wqe_mode(struct bnxt_re_dev *rdev) -{ - return rdev->chip_ctx->modes.wqe_mode; -} - static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd, struct ib_qp_init_attr *init_attr, struct ib_udata *udata) @@ -2111,7 +2190,7 @@ static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd, goto out; } qplqp->type = (u8)qptype; - qplqp->wqe_mode = bnxt_re_init_qp_wqe_mode(rdev); + qplqp->wqe_mode = bnxt_re_is_var_size_supported(rdev, cntx); ether_addr_copy(qplqp->smac, rdev->dev_addr); if (init_attr->qp_type == IB_QPT_RC) { @@ -2158,7 +2237,7 @@ static int bnxt_re_init_qp_attr(struct bnxt_re_qp *qp, struct bnxt_re_pd *pd, bnxt_re_adjust_gsi_rq_attr(qp); /* Setup SQ */ - rc = bnxt_re_init_sq_attr(qp, init_attr, cntx); + rc = bnxt_re_init_sq_attr(qp, init_attr, cntx, udata); if (rc) goto out; if (init_attr->qp_type == IB_QPT_GSI) @@ -2794,6 +2873,7 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr, if (entries > dev_attr->max_qp_wqes) entries = dev_attr->max_qp_wqes; qp->qplib_qp.rq.max_wqe = entries; + qp->qplib_qp.rq.max_sw_wqe = qp->qplib_qp.rq.max_wqe; qp->qplib_qp.rq.q_full_delta = qp->qplib_qp.rq.max_wqe - qp_attr->cap.max_recv_wr; qp->qplib_qp.rq.max_sge = qp_attr->cap.max_recv_sge; @@ -5294,11 +5374,9 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *uctx_in, } genp5 = _is_chip_gen_p5_p7(cctx); - if (BNXT_RE_ABI_VERSION > 5) { - resp.modes = genp5 ? cctx->modes.wqe_mode : 0; - if (rdev->dev_attr && BNXT_RE_HW_RETX(rdev->dev_attr->dev_cap_flags)) - resp.comp_mask = BNXT_RE_COMP_MASK_UCNTX_HW_RETX_ENABLED; - } + resp.mode = genp5 ? cctx->modes.wqe_mode : 0; + if (rdev->dev_attr && _is_host_msn_table(rdev->dev_attr->dev_cap_ext_flags2)) + resp.comp_mask = BNXT_RE_COMP_MASK_UCNTX_HW_RETX_ENABLED; resp.pg_size = PAGE_SIZE; resp.cqe_sz = sizeof(struct cq_base); @@ -5331,6 +5409,12 @@ int bnxt_re_alloc_ucontext(struct ib_ucontext *uctx_in, if (bnxt_re_init_rsvd_wqe_flag(&ureq, &resp, genp5)) dev_warn(rdev_to_dev(rdev), "Rsvd wqe in use! Try the updated library.\n"); + if (ureq.comp_mask & BNXT_RE_COMP_MASK_REQ_UCNTX_VAR_WQE_SUPPORT) { + resp.comp_mask |= BNXT_RE_COMP_MASK_UCNTX_CMASK_HAVE_MODE; + resp.mode = rdev->chip_ctx->modes.wqe_mode; + if (resp.mode == BNXT_QPLIB_WQE_MODE_VARIABLE) + resp.comp_mask |= BNXT_RE_UCNTX_CAP_VAR_WQE_ENABLED; + } } else { dev_warn(rdev_to_dev(rdev), "Enabled roundup logic. Update the library!\n"); diff --git a/sys/dev/bnxt/bnxt_re/ib_verbs.h b/sys/dev/bnxt/bnxt_re/ib_verbs.h index cb9f7974e92d..66d15dd2b767 100644 --- a/sys/dev/bnxt/bnxt_re/ib_verbs.h +++ b/sys/dev/bnxt/bnxt_re/ib_verbs.h @@ -49,10 +49,22 @@ struct bnxt_re_dev; #define SPEED_1000 1000 #endif +#ifndef SPEED_2500 +#define SPEED_2500 2500 +#endif + +#ifndef SPEED_5000 +#define SPEED_5000 5000 +#endif + #ifndef SPEED_10000 #define SPEED_10000 10000 #endif +#ifndef SPEED_14000 +#define SPEED_14000 14000 +#endif + #ifndef SPEED_20000 #define SPEED_20000 20000 #endif @@ -77,10 +89,18 @@ struct bnxt_re_dev; #define SPEED_200000 200000 #endif +#ifndef SPEED_400000 +#define SPEED_400000 400000 +#endif + #ifndef IB_SPEED_HDR #define IB_SPEED_HDR 64 #endif +#ifndef IB_SPEED_NDR +#define IB_SPEED_NDR 128 +#endif + #define RDMA_NETWORK_IPV4 1 #define RDMA_NETWORK_IPV6 2 @@ -488,6 +508,11 @@ static inline int bnxt_re_init_pow2_flag(struct bnxt_re_uctx_req *req, return 0; } +enum { + BNXT_RE_UCNTX_CAP_POW2_DISABLED = 0x1ULL, + BNXT_RE_UCNTX_CAP_VAR_WQE_ENABLED = 0x2ULL, +}; + static inline u32 bnxt_re_init_depth(u32 ent, struct bnxt_re_ucontext *uctx) { return uctx ? (uctx->cmask & BNXT_RE_COMP_MASK_UCNTX_POW2_DISABLED) ? diff --git a/sys/dev/bnxt/bnxt_re/main.c b/sys/dev/bnxt/bnxt_re/main.c index 3d26d21f3fc7..01c2710bc3ea 100644 --- a/sys/dev/bnxt/bnxt_re/main.c +++ b/sys/dev/bnxt/bnxt_re/main.c @@ -1101,7 +1101,6 @@ static int bnxt_re_handle_start(struct auxiliary_device *adev) rc = bnxt_re_add_device(&rdev, real_dev, en_info->gsi_mode, BNXT_RE_POST_RECOVERY_INIT, - en_info->wqe_mode, en_info->num_msix_requested, adev); if (rc) { /* Add device failed. Unregister the device. @@ -1411,12 +1410,14 @@ static void bnxt_re_set_db_offset(struct bnxt_re_dev *rdev) dev_info(rdev_to_dev(rdev), "Couldn't get DB bar size, Low latency framework is disabled\n"); /* set register offsets for both UC and WC */ - if (_is_chip_p7(cctx)) - res->dpi_tbl.ucreg.offset = offset; - else + if (_is_chip_p7(cctx)) { + res->dpi_tbl.ucreg.offset = en_dev->l2_db_offset; + res->dpi_tbl.wcreg.offset = en_dev->l2_db_size; + } else { res->dpi_tbl.ucreg.offset = res->is_vf ? BNXT_QPLIB_DBR_VF_DB_OFFSET : BNXT_QPLIB_DBR_PF_DB_OFFSET; - res->dpi_tbl.wcreg.offset = res->dpi_tbl.ucreg.offset; + res->dpi_tbl.wcreg.offset = res->dpi_tbl.ucreg.offset; + } /* If WC mapping is disabled by L2 driver then en_dev->l2_db_size * is equal to the DB-Bar actual size. This indicates that L2 @@ -1433,15 +1434,15 @@ static void bnxt_re_set_db_offset(struct bnxt_re_dev *rdev) return; } -static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev, u8 mode) +static void bnxt_re_set_drv_mode(struct bnxt_re_dev *rdev) { struct bnxt_qplib_chip_ctx *cctx; struct bnxt_en_dev *en_dev; en_dev = rdev->en_dev; cctx = rdev->chip_ctx; - cctx->modes.wqe_mode = _is_chip_gen_p5_p7(rdev->chip_ctx) ? - mode : BNXT_QPLIB_WQE_MODE_STATIC; + cctx->modes.wqe_mode = _is_chip_p7(rdev->chip_ctx) ? + BNXT_QPLIB_WQE_MODE_VARIABLE : BNXT_QPLIB_WQE_MODE_STATIC; cctx->modes.te_bypass = false; if (bnxt_re_hwrm_qcaps(rdev)) dev_err(rdev_to_dev(rdev), @@ -1490,7 +1491,7 @@ static void bnxt_re_destroy_chip_ctx(struct bnxt_re_dev *rdev) kfree(chip_ctx); } -static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode) +static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev) { struct bnxt_qplib_chip_ctx *chip_ctx; struct bnxt_en_dev *en_dev; @@ -1525,7 +1526,7 @@ static int bnxt_re_setup_chip_ctx(struct bnxt_re_dev *rdev, u8 wqe_mode) rc = -ENOMEM; goto fail; } - bnxt_re_set_drv_mode(rdev, wqe_mode); + bnxt_re_set_drv_mode(rdev); bnxt_re_set_db_offset(rdev); rc = bnxt_qplib_map_db_bar(&rdev->qplib_res); @@ -2029,11 +2030,30 @@ static ssize_t show_hca(struct device *device, struct device_attribute *attr, return scnprintf(buf, PAGE_SIZE, "%s\n", rdev->ibdev.node_desc); } +static ssize_t show_board_id(struct device *device, struct device_attribute *attr, + char *buf) +{ + struct bnxt_re_dev *rdev = to_bnxt_re_dev(device, ibdev.dev); + char buffer[BNXT_VPD_PN_FLD_LEN] = {}; + + if (!rdev->is_virtfn) + memcpy(buffer, rdev->en_dev->board_part_number, + BNXT_VPD_PN_FLD_LEN - 1); + else + scnprintf(buffer, BNXT_VPD_PN_FLD_LEN, + "0x%x-VF", rdev->en_dev->pdev->device); + + return scnprintf(buf, PAGE_SIZE, "%s\n", buffer); +} + static DEVICE_ATTR(hw_rev, 0444, show_rev, NULL); static DEVICE_ATTR(hca_type, 0444, show_hca, NULL); +static DEVICE_ATTR(board_id, 0444, show_board_id, NULL); + static struct device_attribute *bnxt_re_attributes[] = { &dev_attr_hw_rev, - &dev_attr_hca_type + &dev_attr_hca_type, + &dev_attr_board_id }; int ib_register_device_compat(struct bnxt_re_dev *rdev) @@ -3530,7 +3550,7 @@ static void bnxt_re_dev_uninit(struct bnxt_re_dev *rdev, u8 op_type) } } -static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type, u8 wqe_mode) +static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type) { struct bnxt_re_ring_attr rattr = {}; struct bnxt_qplib_creq_ctx *creq; @@ -3545,7 +3565,7 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type, u8 wqe_mode) } set_bit(BNXT_RE_FLAG_NETDEV_REGISTERED, &rdev->flags); - rc = bnxt_re_setup_chip_ctx(rdev, wqe_mode); + rc = bnxt_re_setup_chip_ctx(rdev); if (rc) { dev_err(rdev_to_dev(rdev), "Failed to get chip context rc 0x%x", rc); bnxt_re_unregister_netdev(rdev); @@ -3592,19 +3612,24 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 op_type, u8 wqe_mode) goto release_rtnl; } + set_bit(BNXT_RE_FLAG_NET_RING_ALLOC, &rdev->flags); + if (!rdev->chip_ctx) goto release_rtnl; - /* Program the NQ ID for DBQ notification */ - if (rdev->chip_ctx->modes.dbr_pacing_v0 || - bnxt_qplib_dbr_pacing_en(rdev->chip_ctx) || - bnxt_qplib_dbr_pacing_ext_en(rdev->chip_ctx)) { - rc = bnxt_re_initialize_dbr_pacing(rdev); - if (!rc) - rdev->dbr_pacing = true; - else - rdev->dbr_pacing = false; - dev_dbg(rdev_to_dev(rdev), "%s: initialize db pacing ret %d\n", - __func__, rc); + + if (!(_is_chip_p7(rdev->chip_ctx))) { + /* Program the NQ ID for DBQ notification */ + if (rdev->chip_ctx->modes.dbr_pacing_v0 || + bnxt_qplib_dbr_pacing_en(rdev->chip_ctx) || + bnxt_qplib_dbr_pacing_ext_en(rdev->chip_ctx)) { + rc = bnxt_re_initialize_dbr_pacing(rdev); + if (!rc) + rdev->dbr_pacing = true; + else + rdev->dbr_pacing = false; + dev_dbg(rdev_to_dev(rdev), "%s: initialize db pacing ret %d\n", + __func__, rc); + } } vec = rdev->nqr.msix_entries[BNXT_RE_AEQ_IDX].vector; @@ -3811,6 +3836,7 @@ static int bnxt_re_dev_reg(struct bnxt_re_dev **rdev, struct ifnet *netdev, void bnxt_re_get_link_speed(struct bnxt_re_dev *rdev) { rdev->espeed = rdev->en_dev->espeed; + rdev->lanes = rdev->en_dev->lanes; return; } @@ -3852,7 +3878,7 @@ void bnxt_re_remove_device(struct bnxt_re_dev *rdev, u8 op_type, int bnxt_re_add_device(struct bnxt_re_dev **rdev, struct ifnet *netdev, - u8 qp_mode, u8 op_type, u8 wqe_mode, + u8 qp_mode, u8 op_type, u32 num_msix_requested, struct auxiliary_device *aux_dev) { @@ -3925,7 +3951,7 @@ int bnxt_re_add_device(struct bnxt_re_dev **rdev, rtnl_lock(); en_info->rdev = *rdev; rtnl_unlock(); - rc = bnxt_re_dev_init(*rdev, op_type, wqe_mode); + rc = bnxt_re_dev_init(*rdev, op_type); if (rc) { ref_error: bnxt_re_dev_unreg(*rdev); @@ -4374,7 +4400,6 @@ static int bnxt_re_probe(struct auxiliary_device *adev, rc = bnxt_re_add_device(&rdev, en_dev->net, BNXT_RE_GSI_MODE_ALL, BNXT_RE_COMPLETE_INIT, - BNXT_QPLIB_WQE_MODE_STATIC, BNXT_RE_MSIX_FROM_MOD_PARAM, adev); if (rc) { mutex_unlock(&bnxt_re_mutex); diff --git a/sys/dev/bnxt/bnxt_re/qplib_fp.c b/sys/dev/bnxt/bnxt_re/qplib_fp.c index 3f1b02406f7f..19708302198b 100644 --- a/sys/dev/bnxt/bnxt_re/qplib_fp.c +++ b/sys/dev/bnxt/bnxt_re/qplib_fp.c @@ -388,10 +388,14 @@ static void bnxt_qplib_service_nq(unsigned long data) struct bnxt_qplib_srq *srq; struct nq_srq_event *nqsrqe = (struct nq_srq_event *)nqe; + u8 toggle; q_handle = le32_to_cpu(nqsrqe->srq_handle_low); q_handle |= (u64)le32_to_cpu(nqsrqe->srq_handle_high) << 32; srq = (struct bnxt_qplib_srq *)q_handle; + toggle = (le16_to_cpu(nqe->info10_type) & NQ_CN_TOGGLE_MASK) + >> NQ_CN_TOGGLE_SFT; + srq->dbinfo.toggle = toggle; bnxt_qplib_armen_db(&srq->dbinfo, DBC_DBC_TYPE_SRQ_ARMENA); if (!nq->srqn_handler(nq, @@ -838,15 +842,15 @@ static int bnxt_qplib_alloc_init_swq(struct bnxt_qplib_q *que) int rc = 0; int indx; - que->swq = kcalloc(que->max_wqe, sizeof(*que->swq), GFP_KERNEL); + que->swq = kcalloc(que->max_sw_wqe, sizeof(*que->swq), GFP_KERNEL); if (!que->swq) { rc = -ENOMEM; goto out; } que->swq_start = 0; - que->swq_last = que->max_wqe - 1; - for (indx = 0; indx < que->max_wqe; indx++) + que->swq_last = que->max_sw_wqe - 1; + for (indx = 0; indx < que->max_sw_wqe; indx++) que->swq[indx].next_idx = indx + 1; que->swq[que->swq_last].next_idx = 0; /* Make it circular */ que->swq_last = 0; @@ -875,19 +879,23 @@ static u32 bnxt_qplib_get_stride(void) return sizeof(struct sq_sge); } -static u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que) +u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que, u8 wqe_mode, bool is_sq) { - u8 stride; + u32 slots; - stride = bnxt_qplib_get_stride(); - return (que->wqe_size * que->max_wqe) / stride; + /* Queue depth is the number of slots. */ + slots = (que->wqe_size * que->max_wqe) / sizeof(struct sq_sge); + /* For variable WQE mode, need to align the slots to 256 */ + if (wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE && is_sq) + slots = ALIGN(slots, BNXT_VAR_MAX_SLOT_ALIGN); + return slots; } static u32 _set_sq_size(struct bnxt_qplib_q *que, u8 wqe_mode) { /* For Variable mode supply number of 16B slots */ return (wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) ? - que->max_wqe : bnxt_qplib_get_depth(que); + que->max_wqe : bnxt_qplib_get_depth(que, wqe_mode, true); } static u32 _set_sq_max_slot(u8 wqe_mode) @@ -925,7 +933,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) hwq_attr.res = res; hwq_attr.sginfo = &sq->sginfo; hwq_attr.stride = bnxt_qplib_get_stride(); - hwq_attr.depth = bnxt_qplib_get_depth(sq); + hwq_attr.depth = bnxt_qplib_get_depth(sq, qp->wqe_mode, false); hwq_attr.type = HWQ_TYPE_QUEUE; rc = bnxt_qplib_alloc_init_hwq(&sq->hwq, &hwq_attr); if (rc) @@ -949,7 +957,7 @@ int bnxt_qplib_create_qp1(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) hwq_attr.res = res; hwq_attr.sginfo = &rq->sginfo; hwq_attr.stride = bnxt_qplib_get_stride(); - hwq_attr.depth = bnxt_qplib_get_depth(rq); + hwq_attr.depth = bnxt_qplib_get_depth(rq, qp->wqe_mode, false); hwq_attr.type = HWQ_TYPE_QUEUE; rc = bnxt_qplib_alloc_init_hwq(&rq->hwq, &hwq_attr); if (rc) @@ -1075,8 +1083,11 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) u32 sqsz; qp->cctx = res->cctx; - if (res->dattr) + if (res->dattr) { qp->dev_cap_flags = res->dattr->dev_cap_flags; + qp->is_host_msn_tbl = _is_host_msn_table(res->dattr->dev_cap_ext_flags2); + } + /* General */ req.type = qp->type; req.dpi = cpu_to_le32(qp->dpi->dpi); @@ -1087,7 +1098,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) psn_sz = _is_chip_gen_p5_p7(qp->cctx) ? sizeof(struct sq_psn_search_ext) : sizeof(struct sq_psn_search); - if (BNXT_RE_HW_RETX(qp->dev_cap_flags)) { + if (qp->is_host_msn_tbl) { psn_sz = sizeof(struct sq_msn_search); qp->msn = 0; } @@ -1098,12 +1109,12 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) hwq_attr.res = res; hwq_attr.sginfo = &sq->sginfo; hwq_attr.stride = bnxt_qplib_get_stride(); - hwq_attr.depth = bnxt_qplib_get_depth(sq); + hwq_attr.depth = bnxt_qplib_get_depth(sq, qp->wqe_mode, true); hwq_attr.aux_stride = psn_sz; hwq_attr.aux_depth = (psn_sz) ? _set_sq_size(sq, qp->wqe_mode) : 0; /* Update msn tbl size */ - if (BNXT_RE_HW_RETX(qp->dev_cap_flags) && psn_sz) { + if (qp->is_host_msn_tbl && psn_sz) { if (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC) hwq_attr.aux_depth = roundup_pow_of_two(_set_sq_size(sq, qp->wqe_mode)); else @@ -1131,8 +1142,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) req.sq_pg_size_sq_lvl = pg_sz_lvl; req.sq_fwo_sq_sge = cpu_to_le16(((0 << CMDQ_CREATE_QP_SQ_FWO_SFT) & CMDQ_CREATE_QP_SQ_FWO_MASK) | - ((BNXT_RE_HW_RETX(qp->dev_cap_flags)) ? - BNXT_MSN_TBLE_SGE : sq->max_sge & + (sq->max_sge & CMDQ_CREATE_QP_SQ_SGE_MASK)); req.scq_cid = cpu_to_le32(qp->scq->id); @@ -1141,7 +1151,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp) hwq_attr.res = res; hwq_attr.sginfo = &rq->sginfo; hwq_attr.stride = bnxt_qplib_get_stride(); - hwq_attr.depth = bnxt_qplib_get_depth(rq); + hwq_attr.depth = bnxt_qplib_get_depth(rq, qp->wqe_mode, false); hwq_attr.aux_stride = 0; hwq_attr.aux_depth = 0; hwq_attr.type = HWQ_TYPE_QUEUE; @@ -1764,7 +1774,7 @@ static void bnxt_qplib_fill_psn_search(struct bnxt_qplib_qp *qp, return; /* Handle MSN differently on cap flags */ - if (BNXT_RE_HW_RETX(qp->dev_cap_flags)) { + if (qp->is_host_msn_tbl) { bnxt_qplib_fill_msn_search(qp, wqe, swq); return; } @@ -1897,7 +1907,7 @@ static u16 _translate_q_full_delta(struct bnxt_qplib_q *que, u16 wqe_bytes) } static void bnxt_qplib_pull_psn_buff(struct bnxt_qplib_qp *qp, struct bnxt_qplib_q *sq, - struct bnxt_qplib_swq *swq, bool hw_retx) + struct bnxt_qplib_swq *swq, bool is_host_msn_tbl) { struct bnxt_qplib_hwq *sq_hwq; u32 pg_num, pg_indx; @@ -1909,8 +1919,11 @@ static void bnxt_qplib_pull_psn_buff(struct bnxt_qplib_qp *qp, struct bnxt_qplib return; tail = swq->slot_idx / sq->dbinfo.max_slot; - if (hw_retx) + if (is_host_msn_tbl) { + /* For HW retx use qp msn index */ + tail = qp->msn; tail %= qp->msn_tbl_sz; + } pg_num = (tail + sq_hwq->pad_pgofft) / (PAGE_SIZE / sq_hwq->pad_stride); pg_indx = (tail + sq_hwq->pad_pgofft) % (PAGE_SIZE / sq_hwq->pad_stride); buff = (void *)(sq_hwq->pad_pg[pg_num] + pg_indx * sq_hwq->pad_stride); @@ -1935,6 +1948,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, struct bnxt_qplib_swq *swq; bool sch_handler = false; u16 slots_needed; + bool msn_update; void *base_hdr; void *ext_hdr; __le32 temp32; @@ -1976,7 +1990,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, sw_prod = sq_hwq->prod; swq = bnxt_qplib_get_swqe(sq, &wqe_idx); swq->slot_idx = sw_prod; - bnxt_qplib_pull_psn_buff(qp, sq, swq, BNXT_RE_HW_RETX(qp->dev_cap_flags)); + bnxt_qplib_pull_psn_buff(qp, sq, swq, qp->is_host_msn_tbl); swq->wr_id = wqe->wr_id; swq->type = wqe->type; @@ -2010,6 +2024,9 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, wqe->num_sge, &sw_prod); if (data_len < 0) goto queue_err; + /* Make sure we update MSN table only for wired wqes */ + msn_update = true; + /* Specifics */ switch (wqe->type) { case BNXT_QPLIB_SWQE_TYPE_SEND: @@ -2064,6 +2081,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, ext_sqe->avid = cpu_to_le32(wqe->send.avid & SQ_SEND_AVID_MASK); sq->psn = (sq->psn + 1) & BTH_PSN_MASK; + msn_update = false; } else { sqe->length = cpu_to_le32(data_len); if (qp->mtu) @@ -2157,6 +2175,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, "\tflags = 0x%x\n" "\tinv_l_key = 0x%x\n", sqe->wqe_type, sqe->flags, sqe->inv_l_key); + msn_update = false; break; } case BNXT_QPLIB_SWQE_TYPE_FAST_REG_MR: @@ -2207,6 +2226,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, sqe->zero_based_page_size_log, sqe->l_key, *(u32 *)sqe->length, sqe->numlevels_pbl_page_size_log, ext_sqe->pblptr, ext_sqe->va); + msn_update = false; break; } case BNXT_QPLIB_SWQE_TYPE_BIND_MW: @@ -2236,6 +2256,7 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, sqe->wqe_type, sqe->flags, sqe->access_cntl, sqe->mw_type_zero_based, sqe->parent_l_key, sqe->l_key, sqe->va, ext_sqe->length_lo); + msn_update = false; break; } default: @@ -2243,8 +2264,10 @@ int bnxt_qplib_post_send(struct bnxt_qplib_qp *qp, rc = -EINVAL; goto done; } - swq->next_psn = sq->psn & BTH_PSN_MASK; - bnxt_qplib_fill_psn_search(qp, wqe, swq); + if (!qp->is_host_msn_tbl || msn_update) { + swq->next_psn = sq->psn & BTH_PSN_MASK; + bnxt_qplib_fill_psn_search(qp, wqe, swq); + } queue_err: bnxt_qplib_swq_mod_start(sq, wqe_idx); @@ -2859,6 +2882,32 @@ out: return rc; } +static int bnxt_qplib_get_cqe_sq_cons(struct bnxt_qplib_q *sq, u32 cqe_slot) +{ + struct bnxt_qplib_hwq *sq_hwq; + struct bnxt_qplib_swq *swq; + int cqe_sq_cons = -1; + u32 start, last; + + sq_hwq = &sq->hwq; + + start = sq->swq_start; + last = sq->swq_last; + + while (last != start) { + swq = &sq->swq[last]; + if (swq->slot_idx == cqe_slot) { + cqe_sq_cons = swq->next_idx; + dev_err(&sq_hwq->pdev->dev, "%s: Found cons wqe = %d slot = %d\n", + __func__, cqe_sq_cons, cqe_slot); + break; + } + + last = swq->next_idx; + } + return cqe_sq_cons; +} + static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, struct cq_req *hwcqe, struct bnxt_qplib_cqe **pcqe, int *budget, @@ -2867,8 +2916,9 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, struct bnxt_qplib_qp *qp; struct bnxt_qplib_q *sq; struct bnxt_qplib_cqe *cqe; - u32 cqe_sq_cons; + u32 cqe_sq_cons, slot_num; struct bnxt_qplib_swq *swq; + int cqe_cons; int rc = 0; qp = (struct bnxt_qplib_qp *)le64_to_cpu(hwcqe->qp_handle); @@ -2880,13 +2930,26 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq, } sq = &qp->sq; - cqe_sq_cons = le16_to_cpu(hwcqe->sq_cons_idx) % sq->max_wqe; + cqe_sq_cons = le16_to_cpu(hwcqe->sq_cons_idx) % sq->max_sw_wqe; if (qp->sq.flushed) { dev_dbg(&cq->hwq.pdev->dev, "%s: QPLIB: QP in Flush QP = %p\n", __func__, qp); goto done; } + if (__is_err_cqe_for_var_wqe(qp, hwcqe->status)) { + slot_num = le16_to_cpu(hwcqe->sq_cons_idx); + cqe_cons = bnxt_qplib_get_cqe_sq_cons(sq, slot_num); + if (cqe_cons < 0) { + dev_dbg(&cq->hwq.pdev->dev, "%s: Wrong SQ cons cqe_slot_indx = %d\n", + __func__, slot_num); + goto done; + } + cqe_sq_cons = cqe_cons; + dev_dbg(&cq->hwq.pdev->dev, "%s: cqe_sq_cons = %d swq_last = %d swq_start = %d\n", + __func__, cqe_sq_cons, sq->swq_last, sq->swq_start); + } + /* Require to walk the sq's swq to fabricate CQEs for all previously * signaled SWQEs due to CQE aggregation from the current sq cons * to the cqe_sq_cons @@ -3329,7 +3392,7 @@ static int bnxt_qplib_cq_process_terminal(struct bnxt_qplib_cq *cq, if (cqe_cons == 0xFFFF) goto do_rq; - cqe_cons %= sq->max_wqe; + cqe_cons %= sq->max_sw_wqe; if (qp->sq.flushed) { dev_dbg(&cq->hwq.pdev->dev, "%s: QPLIB: QP in Flush QP = %p\n", __func__, qp); diff --git a/sys/dev/bnxt/bnxt_re/qplib_fp.h b/sys/dev/bnxt/bnxt_re/qplib_fp.h index 527c377f0aa5..542a26782c62 100644 --- a/sys/dev/bnxt/bnxt_re/qplib_fp.h +++ b/sys/dev/bnxt/bnxt_re/qplib_fp.h @@ -300,6 +300,7 @@ struct bnxt_qplib_q { struct bnxt_qplib_sg_info sginfo; struct bnxt_qplib_hwq hwq; u32 max_wqe; + u32 max_sw_wqe; u16 max_sge; u16 wqe_size; u16 q_full_delta; @@ -390,6 +391,7 @@ struct bnxt_qplib_qp { u32 msn_tbl_sz; /* get devflags in PI code */ u16 dev_cap_flags; + bool is_host_msn_tbl; }; @@ -634,5 +636,16 @@ static inline uint64_t bnxt_re_update_msn_tbl(uint32_t st_idx, uint32_t npsn, ui SQ_MSN_SEARCH_START_PSN_MASK)); } +static inline bool __is_var_wqe(struct bnxt_qplib_qp *qp) +{ + return (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE); +} + +static inline bool __is_err_cqe_for_var_wqe(struct bnxt_qplib_qp *qp, u8 status) +{ + return (status != CQ_REQ_STATUS_OK) && __is_var_wqe(qp); +} + void bnxt_re_schedule_dbq_event(struct bnxt_qplib_res *res); +u32 bnxt_qplib_get_depth(struct bnxt_qplib_q *que, u8 wqe_mode, bool is_sq); #endif diff --git a/sys/dev/bnxt/bnxt_re/qplib_res.c b/sys/dev/bnxt/bnxt_re/qplib_res.c index f527af031176..9051f4c9f2b7 100644 --- a/sys/dev/bnxt/bnxt_re/qplib_res.c +++ b/sys/dev/bnxt/bnxt_re/qplib_res.c @@ -1139,7 +1139,8 @@ int bnxt_qplib_map_db_bar(struct bnxt_qplib_res *res) ucreg->bar_id = RCFW_DBR_PCI_BAR_REGION; ucreg->bar_base = pci_resource_start(res->pdev, ucreg->bar_id); - ucreg->offset = 65536; + if (_is_chip_gen_p5(res->cctx)) + ucreg->offset = 65536; ucreg->len = ucreg->offset + PAGE_SIZE; diff --git a/sys/dev/bnxt/bnxt_re/qplib_res.h b/sys/dev/bnxt/bnxt_re/qplib_res.h index 6468207a49aa..59a8a43ecef6 100644 --- a/sys/dev/bnxt/bnxt_re/qplib_res.h +++ b/sys/dev/bnxt/bnxt_re/qplib_res.h @@ -616,6 +616,12 @@ static inline bool _is_hw_retx_supported(u16 dev_cap_flags) /* Disable HW_RETX */ #define BNXT_RE_HW_RETX(a) _is_hw_retx_supported((a)) +static inline bool _is_host_msn_table(u16 dev_cap_ext_flags2) +{ + return (dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_MASK) == + CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_HOST_MSN_TABLE; +} + static inline bool _is_cqe_v2_supported(u16 dev_cap_flags) { return dev_cap_flags & @@ -650,7 +656,7 @@ static inline void bnxt_qplib_ring_db32(struct bnxt_qplib_db_info *info, #define BNXT_QPLIB_INIT_DBHDR(xid, type, indx, toggle) \ (((u64)(((xid) & DBC_DBC_XID_MASK) | DBC_DBC_PATH_ROCE | \ (type) | BNXT_QPLIB_DBR_VALID) << 32) | (indx) | \ - ((toggle) << (BNXT_QPLIB_DBR_TOGGLE_SHIFT))) + (((u32)(toggle)) << (BNXT_QPLIB_DBR_TOGGLE_SHIFT))) static inline void bnxt_qplib_write_db(struct bnxt_qplib_db_info *info, u64 key, void __iomem *db, @@ -724,7 +730,7 @@ static inline void bnxt_qplib_armen_db(struct bnxt_qplib_db_info *info, u64 key = 0; u8 toggle = 0; - if (type == DBC_DBC_TYPE_CQ_ARMENA) + if (type == DBC_DBC_TYPE_CQ_ARMENA || type == DBC_DBC_TYPE_SRQ_ARMENA) toggle = info->toggle; /* Index always at 0 */ key = BNXT_QPLIB_INIT_DBHDR(info->xid, type, 0, toggle); @@ -746,7 +752,7 @@ static inline void bnxt_qplib_srq_arm_db(struct bnxt_qplib_db_info *info) u64 key = 0; /* Index always at 0 */ - key = BNXT_QPLIB_INIT_DBHDR(info->xid, DBC_DBC_TYPE_SRQ_ARM, 0, 0); + key = BNXT_QPLIB_INIT_DBHDR(info->xid, DBC_DBC_TYPE_SRQ_ARM, 0, info->toggle); bnxt_qplib_write_db(info, key, info->priv_db, &info->shadow_key); } @@ -837,4 +843,11 @@ static inline void bnxt_qplib_max_res_supported(struct bnxt_qplib_chip_ctx *cctx break; } } + +static inline u32 bnxt_re_cap_fw_res(u32 fw_val, u32 drv_cap, bool sw_max_en) +{ + if (sw_max_en) + return fw_val; + return min_t(u32, fw_val, drv_cap); +} #endif diff --git a/sys/dev/bnxt/bnxt_re/qplib_sp.c b/sys/dev/bnxt/bnxt_re/qplib_sp.c index c414718a816f..f876573ce69f 100644 --- a/sys/dev/bnxt/bnxt_re/qplib_sp.c +++ b/sys/dev/bnxt/bnxt_re/qplib_sp.c @@ -40,6 +40,7 @@ #include "qplib_res.h" #include "qplib_rcfw.h" #include "qplib_sp.h" +#include "bnxt_ulp.h" const struct bnxt_qplib_gid bnxt_qplib_gid_zero = {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }}; @@ -79,6 +80,7 @@ static void bnxt_qplib_query_version(struct bnxt_qplib_rcfw *rcfw, char *fw_ver) int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw) { + struct bnxt_qplib_max_res dev_res = {}; struct creq_query_func_resp resp = {}; struct bnxt_qplib_cmdqmsg msg = {}; struct creq_query_func_resp_sb *sb; @@ -86,10 +88,10 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw) struct bnxt_qplib_dev_attr *attr; struct bnxt_qplib_chip_ctx *cctx; struct cmdq_query_func req = {}; + bool sw_max_en; u8 *tqm_alloc; int i, rc = 0; u32 temp; - u8 chip_gen = BNXT_RE_DEFAULT; cctx = rcfw->res->cctx; attr = rcfw->res->dattr; @@ -110,10 +112,11 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw) rc = bnxt_qplib_rcfw_send_message(rcfw, &msg); if (rc) goto bail; + bnxt_qplib_max_res_supported(cctx, rcfw->res, &dev_res, false); + sw_max_en = BNXT_EN_SW_RES_LMT(rcfw->res->en_dev); /* Extract the context from the side buffer */ - chip_gen = _get_chip_gen_p5_type(cctx); - attr->max_qp = le32_to_cpu(sb->max_qp); - attr->max_qp = min_t(u32, attr->max_qp, BNXT_RE_MAX_QP_SUPPORTED(chip_gen)); + attr->max_qp = bnxt_re_cap_fw_res(le32_to_cpu(sb->max_qp), + dev_res.max_qp, sw_max_en); /* max_qp value reported by FW does not include the QP1 */ attr->max_qp += 1; attr->max_qp_rd_atom = @@ -126,11 +129,6 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw) * one extra entry while creating the qp */ attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr) - 1; - /* Adjust for max_qp_wqes for variable wqe */ - if (cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) { - attr->max_qp_wqes = (BNXT_MAX_SQ_SIZE) / - (BNXT_MAX_VAR_WQE_SIZE / BNXT_SGE_SIZE) - 1; - } if (!_is_chip_gen_p5_p7(cctx)) { /* * 128 WQEs needs to be reserved for the HW (8916). Prevent @@ -138,33 +136,36 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw) */ attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS; } - attr->max_qp_sges = sb->max_sge; - if (_is_chip_gen_p5_p7(cctx) && - cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) - attr->max_qp_sges = sb->max_sge_var_wqe; - attr->max_cq = le32_to_cpu(sb->max_cq); - attr->max_cq = min_t(u32, attr->max_cq, BNXT_RE_MAX_CQ_SUPPORTED(chip_gen)); + + /* Adjust for max_qp_wqes for variable wqe */ + if (cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE) + attr->max_qp_wqes = BNXT_VAR_MAX_WQE - 1; + + attr->max_qp_sges = cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE ? + min_t(u32, sb->max_sge_var_wqe, BNXT_VAR_MAX_SGE) : sb->max_sge; + attr->max_cq = bnxt_re_cap_fw_res(le32_to_cpu(sb->max_cq), + dev_res.max_cq, sw_max_en); attr->max_cq_wqes = le32_to_cpu(sb->max_cqe); attr->max_cq_wqes = min_t(u32, BNXT_QPLIB_MAX_CQ_WQES, attr->max_cq_wqes); attr->max_cq_sges = attr->max_qp_sges; - attr->max_mr = le32_to_cpu(sb->max_mr); - attr->max_mr = min_t(u32, attr->max_mr, BNXT_RE_MAX_MRW_SUPPORTED(chip_gen)); - attr->max_mw = le32_to_cpu(sb->max_mw); - attr->max_mw = min_t(u32, attr->max_mw, BNXT_RE_MAX_MRW_SUPPORTED(chip_gen)); + attr->max_mr = bnxt_re_cap_fw_res(le32_to_cpu(sb->max_mr), + dev_res.max_mr, sw_max_en); + attr->max_mw = bnxt_re_cap_fw_res(le32_to_cpu(sb->max_mw), + dev_res.max_mr, sw_max_en); attr->max_mr_size = le64_to_cpu(sb->max_mr_size); attr->max_pd = BNXT_QPLIB_MAX_PD; attr->max_raw_ethy_qp = le32_to_cpu(sb->max_raw_eth_qp); - attr->max_ah = le32_to_cpu(sb->max_ah); - attr->max_ah = min_t(u32, attr->max_ah, BNXT_RE_MAX_AH_SUPPORTED(chip_gen)); + attr->max_ah = bnxt_re_cap_fw_res(le32_to_cpu(sb->max_ah), + dev_res.max_ah, sw_max_en); attr->max_fmr = le32_to_cpu(sb->max_fmr); attr->max_map_per_fmr = sb->max_map_per_fmr; - attr->max_srq = le16_to_cpu(sb->max_srq); - attr->max_srq = min_t(u32, attr->max_srq, BNXT_RE_MAX_SRQ_SUPPORTED(chip_gen)); + attr->max_srq = bnxt_re_cap_fw_res(le16_to_cpu(sb->max_srq), + dev_res.max_srq, sw_max_en); attr->max_srq_wqes = le32_to_cpu(sb->max_srq_wr) - 1; attr->max_srq_sges = sb->max_srq_sge; attr->max_pkey = 1; @@ -185,6 +186,7 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw) attr->page_size_cap = BIT_ULL(28) | BIT_ULL(21) | BIT_ULL(12); bnxt_qplib_query_version(rcfw, attr->fw_ver); + attr->dev_cap_ext_flags2 = le16_to_cpu(sb->dev_cap_ext_flags_2); for (i = 0; i < MAX_TQM_ALLOC_REQ / 4; i++) { temp = le32_to_cpu(sb->tqm_alloc_reqs[i]); diff --git a/sys/dev/bnxt/bnxt_re/qplib_sp.h b/sys/dev/bnxt/bnxt_re/qplib_sp.h index e306db3b9d8e..5a5485dc5250 100644 --- a/sys/dev/bnxt/bnxt_re/qplib_sp.h +++ b/sys/dev/bnxt/bnxt_re/qplib_sp.h @@ -32,6 +32,7 @@ #define __BNXT_QPLIB_SP_H__ #include <rdma/ib_verbs.h> +#include "bnxt_re-abi.h" #define BNXT_QPLIB_RESERVED_QP_WRS 128 @@ -71,6 +72,7 @@ struct bnxt_qplib_dev_attr { u32 l2_db_size; u8 tqm_alloc_reqs[MAX_TQM_ALLOC_REQ]; u8 is_atomic; + u16 dev_cap_ext_flags2; u16 dev_cap_flags; u64 page_size_cap; u32 max_dpi; @@ -394,6 +396,13 @@ bool ib_modify_qp_is_ok_compat(enum ib_qp_state cur_state, enum ib_qp_state next #define BNXT_MAX_VAR_WQE_SIZE 512 #define BNXT_SGE_SIZE 16 +#define BNXT_VAR_MAX_WQE 4352 +#define BNXT_VAR_MAX_SLOT_ALIGN 256 +#define BNXT_VAR_MAX_SGE 13 +#define BNXT_RE_MAX_RQ_WQES 65536 + +#define BNXT_STATIC_MAX_SGE 6 + /* PF defines */ #define BNXT_RE_MAX_QP_SUPPORTED(chip_gen) \ chip_gen == BNXT_RE_DEFAULT ? (64 * 1024) : 0 diff --git a/sys/dev/cfe/cfe_resource.c b/sys/dev/cfe/cfe_resource.c index 78c5f149ba7d..223178e36e47 100644 --- a/sys/dev/cfe/cfe_resource.c +++ b/sys/dev/cfe/cfe_resource.c @@ -144,7 +144,7 @@ static device_method_t cferes_methods[] = { DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t cferes_driver = { diff --git a/sys/dev/cfi/cfi_disk.c b/sys/dev/cfi/cfi_disk.c index 4c3eae473fb6..3beef8821ae4 100644 --- a/sys/dev/cfi/cfi_disk.c +++ b/sys/dev/cfi/cfi_disk.c @@ -346,7 +346,7 @@ static device_method_t cfi_disk_methods[] = { DEVMETHOD(device_probe, cfi_disk_probe), DEVMETHOD(device_attach, cfi_disk_attach), DEVMETHOD(device_detach, cfi_disk_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t cfi_disk_driver = { "cfid", diff --git a/sys/dev/chromebook_platform/chromebook_platform.c b/sys/dev/chromebook_platform/chromebook_platform.c index f873338a3ba6..c7c1ff4222a1 100644 --- a/sys/dev/chromebook_platform/chromebook_platform.c +++ b/sys/dev/chromebook_platform/chromebook_platform.c @@ -82,7 +82,7 @@ chromebook_i2c_identify(driver_t *driver, device_t bus) static device_method_t chromebook_i2c_methods[] = { DEVMETHOD(device_identify, chromebook_i2c_identify), - { 0, 0 } + DEVMETHOD_END }; static driver_t chromebook_i2c_driver = { diff --git a/sys/dev/ciss/ciss.c b/sys/dev/ciss/ciss.c index dd3df631119a..416f6e86e663 100644 --- a/sys/dev/ciss/ciss.c +++ b/sys/dev/ciss/ciss.c @@ -217,7 +217,7 @@ static device_method_t ciss_methods[] = { DEVMETHOD(device_attach, ciss_attach), DEVMETHOD(device_detach, ciss_detach), DEVMETHOD(device_shutdown, ciss_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t ciss_pci_driver = { diff --git a/sys/dev/clk/allwinner/ccu_h616.c b/sys/dev/clk/allwinner/ccu_h616.c new file mode 100644 index 000000000000..ea112fbf8ea4 --- /dev/null +++ b/sys/dev/clk/allwinner/ccu_h616.c @@ -0,0 +1,493 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2019 Emmanuel Vadot <manu@freebsd.org> + * Copyright (c) 2025 The FreeBSD Foundation + * + * Portions of this file were written by Tom Jones <thj@freebsd.org> under + * sponsorship from The FreeBSD Foundation. + * + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/rman.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> + +#include <dev/fdt/simplebus.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/clk/clk_div.h> +#include <dev/clk/clk_fixed.h> +#include <dev/clk/clk_mux.h> + +#include <dev/clk/allwinner/aw_ccung.h> + +#include <dt-bindings/clock/sun50i-h616-ccu.h> +#include <dt-bindings/reset/sun50i-h616-ccu.h> + +/* Non-exported clocks */ +#define CLK_OSC_24M 0 +#define CLK_PLL_CPUX 1 +#define CLK_PLL_AUDIO 2 +#define CLK_PLL_PERIPH0_2X 4 +#define CLK_PLL_PERIPH1_2X 5 +#define CLK_PLL_PERIPH1 6 +#define CLK_PLL_VIDEO0_4X 8 +#define CLK_PLL_VIDEO1_4X 9 +#define CLK_PLL_VIDEO0 10 +#define CLK_PLL_VIDEO1 12 +#define CLK_PLL_VIDEO2 12 +#define CLK_PLL_VE 14 +#define CLK_PLL_DDR0 9 +#define CLK_PLL_DDR1 9 +#define CLK_PLL_DE 14 +#define CLK_PLL_GPU 16 + +#define CLK_PSI_AHB1_AHB2 24 +#define CLK_AHB3 25 +#define CLK_APB2 27 + +static struct aw_ccung_reset h616_ccu_resets[] = { + /* PSI_BGR_REG */ + CCU_RESET(RST_BUS_PSI, 0x79c, 16) + + /* SMHC_BGR_REG */ + CCU_RESET(RST_BUS_MMC0, 0x84c, 16) + CCU_RESET(RST_BUS_MMC1, 0x84c, 17) + CCU_RESET(RST_BUS_MMC2, 0x84c, 18) + + /* UART_BGR_REG */ + CCU_RESET(RST_BUS_UART0, 0x90c, 16) + CCU_RESET(RST_BUS_UART1, 0x90c, 17) + CCU_RESET(RST_BUS_UART2, 0x90c, 18) + CCU_RESET(RST_BUS_UART3, 0x90c, 19) + CCU_RESET(RST_BUS_UART4, 0x90c, 20) + CCU_RESET(RST_BUS_UART5, 0x90c, 21) + + /* TWI_BGR_REG */ + CCU_RESET(RST_BUS_I2C0, 0x91c, 16) + CCU_RESET(RST_BUS_I2C1, 0x91c, 17) + CCU_RESET(RST_BUS_I2C2, 0x91c, 18) + CCU_RESET(RST_BUS_I2C3, 0x91c, 19) + CCU_RESET(RST_BUS_I2C4, 0x91c, 20) + + /* EMAC_BGR_REG */ + CCU_RESET(RST_BUS_EMAC0, 0x97c, 16) + CCU_RESET(RST_BUS_EMAC1, 0x97c, 17) + + /* USB0_CLK_REG */ + CCU_RESET(RST_USB_PHY0, 0xa70, 30) + + /* USB1_CLK_REG */ + CCU_RESET(RST_USB_PHY1, 0xa74, 30) + + /* USB2_CLK_REG */ + CCU_RESET(RST_USB_PHY2, 0xa78, 30) + + /* USB2_CLK_REG */ + CCU_RESET(RST_USB_PHY3, 0xa7c, 30) + + /* USB_BGR_REG */ + CCU_RESET(RST_BUS_OHCI0, 0xa8c, 16) + CCU_RESET(RST_BUS_OHCI1, 0xa8c, 17) + CCU_RESET(RST_BUS_OHCI2, 0xa8c, 18) + CCU_RESET(RST_BUS_OHCI3, 0xa8c, 19) + CCU_RESET(RST_BUS_EHCI0, 0xa8c, 20) + CCU_RESET(RST_BUS_EHCI1, 0xa8c, 21) + CCU_RESET(RST_BUS_EHCI2, 0xa8c, 22) + CCU_RESET(RST_BUS_EHCI3, 0xa8c, 23) + CCU_RESET(RST_BUS_OTG, 0xa8c, 24) +}; + +static struct aw_ccung_gate h616_ccu_gates[] = { + /* PSI_BGR_REG */ + CCU_GATE(CLK_BUS_PSI, "bus-psi", "psi_ahb1_ahb2", 0x79c, 0) + + /* SMHC_BGR_REG */ + CCU_GATE(CLK_BUS_MMC0, "bus-mmc0", "ahb3", 0x84c, 0) + CCU_GATE(CLK_BUS_MMC1, "bus-mmc1", "ahb3", 0x84c, 1) + CCU_GATE(CLK_BUS_MMC2, "bus-mmc2", "ahb3", 0x84c, 2) + + /* + * XXX-THJ: Inheritied comment from H6: + * UART_BGR_REG Enabling the gate enable weird behavior ... + */ + /* CCU_GATE(CLK_BUS_UART0, "bus-uart0", "apb2", 0x90c, 0) */ + /* CCU_GATE(CLK_BUS_UART1, "bus-uart1", "apb2", 0x90c, 1) */ + /* CCU_GATE(CLK_BUS_UART2, "bus-uart2", "apb2", 0x90c, 2) */ + /* CCU_GATE(CLK_BUS_UART3, "bus-uart3", "apb2", 0x90c, 3) */ + /* CCU_GATE(CLK_BUS_UART4, "bus-uart4", "apb2", 0x90c, 4) */ + /* CCU_GATE(CLK_BUS_UART5, "bus-uart5", "apb2", 0x90c, 5) */ + + /* TWI_BGR_REG */ + CCU_GATE(CLK_BUS_I2C0, "bus-i2c0", "apb2", 0x91c, 0) + CCU_GATE(CLK_BUS_I2C1, "bus-i2c1", "apb2", 0x91c, 1) + CCU_GATE(CLK_BUS_I2C2, "bus-i2c2", "apb2", 0x91c, 2) + CCU_GATE(CLK_BUS_I2C3, "bus-i2c3", "apb2", 0x91c, 3) + + /* EMAC_BGR_REG */ + CCU_GATE(CLK_BUS_EMAC0, "bus-emac0", "ahb3", 0x97c, 0) + CCU_GATE(CLK_BUS_EMAC1, "bus-emac1", "ahb3", 0x97c, 1) + + /* USB0_CLK_REG */ + CCU_GATE(CLK_USB_PHY0, "usb-phy0", "ahb3", 0xa70, 29) + CCU_GATE(CLK_USB_OHCI0, "usb-ohci0", "ahb3", 0xa70, 31) + + /* USB1_CLK_REG */ + CCU_GATE(CLK_USB_PHY1, "usb-phy1", "ahb3", 0xa74, 29) + CCU_GATE(CLK_USB_OHCI1, "usb-ohci1", "ahb3", 0xa74, 31) + + /* USB2_CLK_REG */ + CCU_GATE(CLK_USB_PHY2, "usb-phy2", "ahb3", 0xa78, 29) + CCU_GATE(CLK_USB_OHCI2, "usb-ohci2", "ahb3", 0xa78, 31) + + /* USB3_CLK_REG */ + CCU_GATE(CLK_USB_PHY3, "usb-phy3", "ahb3", 0xa7c, 29) + CCU_GATE(CLK_USB_OHCI3, "usb-ohci3", "ahb3", 0xa7c, 31) + + /* USB_BGR_REG */ + CCU_GATE(CLK_BUS_OHCI0, "bus-ohchi0", "ahb3", 0xa8c, 0) + CCU_GATE(CLK_BUS_OHCI1, "bus-ohchi1", "ahb3", 0xa8c, 1) + CCU_GATE(CLK_BUS_OHCI2, "bus-ohchi2", "ahb3", 0xa8c, 2) + CCU_GATE(CLK_BUS_OHCI3, "bus-ohchi3", "ahb3", 0xa8c, 3) + CCU_GATE(CLK_BUS_EHCI0, "bus-ehchi0", "ahb3", 0xa8c, 4) + CCU_GATE(CLK_BUS_EHCI1, "bus-ehchi1", "ahb3", 0xa8c, 5) + CCU_GATE(CLK_BUS_EHCI2, "bus-ehchi2", "ahb3", 0xa8c, 6) + CCU_GATE(CLK_BUS_EHCI3, "bus-ehchi3", "ahb3", 0xa8c, 7) + CCU_GATE(CLK_BUS_OTG, "bus-otg", "ahb3", 0xa8c, 8) +}; + +static const char *pll_cpux_parents[] = {"osc24M"}; +NP_CLK(pll_cpux_clk, + CLK_PLL_CPUX, /* id */ + "pll_cpux", pll_cpux_parents, /* name, parents */ + 0x00, /* offset */ + 8, 8, 0, 0, /* n factor */ + 16, 2, 0, 0, /* p factor */ + 31, /* gate */ + 28, 1000, /* lock */ + AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */ + +static const char *pll_ddr0_parents[] = {"osc24M"}; +NMM_CLK(pll_ddr0_clk, + CLK_PLL_DDR0, /* id */ + "pll_ddr0", pll_ddr0_parents, /* name, parents */ + 0x10, /* offset */ + 8, 8, 0, 0, /* n factor */ + 0, 1, 0, 0, /* m0 factor */ + 1, 1, 0, 0, /* m1 factor */ + 31, /* gate */ + 28, 1000, /* lock */ + AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */ + +static const char *pll_ddr1_parents[] = {"osc24M"}; +NMM_CLK(pll_ddr1_clk, + CLK_PLL_DDR1, /* id */ + "pll_ddr1", pll_ddr1_parents, /* name, parents */ + 0x18, /* offset */ + 8, 8, 0, 0, /* n factor */ + 0, 1, 0, 0, /* m0 factor */ + 1, 1, 0, 0, /* m1 factor */ + 31, /* gate */ + 28, 1000, /* lock */ + AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */ + +static const char *pll_peri0_2x_parents[] = {"osc24M"}; +NMM_CLK(pll_peri0_2x_clk, + CLK_PLL_PERIPH0_2X, /* id */ + "pll_periph0_2x", pll_peri0_2x_parents, /* name, parents */ + 0x20, /* offset */ + 8, 8, 0, 0, /* n factor */ + 0, 1, 0, 0, /* m0 factor */ + 1, 1, 0, 0, /* m1 factor */ + 31, /* gate */ + 28, 1000, /* lock */ + AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */ +static const char *pll_peri0_parents[] = {"pll_periph0_2x"}; +FIXED_CLK(pll_peri0_clk, + CLK_PLL_PERIPH0, /* id */ + "pll_periph0", /* name */ + pll_peri0_parents, /* parent */ + 0, /* freq */ + 1, /* mult */ + 2, /* div */ + 0); /* flags */ + +static const char *pll_peri1_2x_parents[] = {"osc24M"}; +NMM_CLK(pll_peri1_2x_clk, + CLK_PLL_PERIPH1_2X, /* id */ + "pll_periph1_2x", pll_peri1_2x_parents, /* name, parents */ + 0x28, /* offset */ + 8, 8, 0, 0, /* n factor */ + 0, 1, 0, 0, /* m0 factor */ + 1, 1, 0, 0, /* m1 factor */ + 31, /* gate */ + 28, 1000, /* lock */ + AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */ +static const char *pll_peri1_parents[] = {"pll_periph1_2x"}; +FIXED_CLK(pll_peri1_clk, + CLK_PLL_PERIPH1, /* id */ + "pll_periph1", /* name */ + pll_peri1_parents, /* parent */ + 0, /* freq */ + 1, /* mult */ + 2, /* div */ + 0); /* flags */ + +static const char *pll_gpu_parents[] = {"osc24M"}; +NMM_CLK(pll_gpu_clk, + CLK_PLL_GPU, /* id */ + "pll_gpu", pll_gpu_parents, /* name, parents */ + 0x30, /* offset */ + 8, 8, 0, 0, /* n factor */ + 0, 1, 0, 0, /* m0 factor */ + 1, 1, 0, 0, /* m1 factor */ + 31, /* gate */ + 28, 1000, /* lock */ + AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */ + +static const char *pll_video0_4x_parents[] = {"osc24M"}; +NMM_CLK(pll_video0_4x_clk, + CLK_PLL_VIDEO0_4X, /* id */ + "pll_video0_4x", pll_video0_4x_parents, /* name, parents */ + 0x40, /* offset */ + 8, 8, 0, 0, /* n factor */ + 0, 1, 0, 0, /* m0 factor */ + 1, 1, 0, 0, /* m1 factor */ + 31, /* gate */ + 28, 1000, /* lock */ + AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */ +static const char *pll_video0_parents[] = {"pll_video0_4x"}; +FIXED_CLK(pll_video0_clk, + CLK_PLL_VIDEO0, /* id */ + "pll_video0", /* name */ + pll_video0_parents, /* parent */ + 0, /* freq */ + 1, /* mult */ + 4, /* div */ + 0); /* flags */ + +static const char *pll_video1_4x_parents[] = {"osc24M"}; +NMM_CLK(pll_video1_4x_clk, + CLK_PLL_VIDEO1_4X, /* id */ + "pll_video1_4x", pll_video1_4x_parents, /* name, parents */ + 0x48, /* offset */ + 8, 8, 0, 0, /* n factor */ + 0, 1, 0, 0, /* m0 factor */ + 1, 1, 0, 0, /* m1 factor */ + 31, /* gate */ + 28, 1000, /* lock */ + AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */ +static const char *pll_video1_parents[] = {"pll_video1_4x"}; +FIXED_CLK(pll_video1_clk, + CLK_PLL_VIDEO1, /* id */ + "pll_video1", /* name */ + pll_video1_parents, /* parent */ + 0, /* freq */ + 1, /* mult */ + 4, /* div */ + 0); /* flags */ + +static const char *pll_video2_4x_parents[] = {"osc24M"}; +NMM_CLK(pll_video2_4x_clk, + CLK_PLL_VIDEO1_4X, /* id */ + "pll_video2_4x", pll_video2_4x_parents, /* name, parents */ + 0x50, /* offset */ + 8, 8, 0, 0, /* n factor */ + 0, 1, 0, 0, /* m0 factor */ + 1, 1, 0, 0, /* m1 factor */ + 31, /* gate */ + 28, 1000, /* lock */ + AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */ +static const char *pll_video2_parents[] = {"pll_video2_4x"}; +FIXED_CLK(pll_video2_clk, + CLK_PLL_VIDEO1, /* id */ + "pll_video2", /* name */ + pll_video2_parents, /* parent */ + 0, /* freq */ + 1, /* mult */ + 4, /* div */ + 0); /* flags */ + +static const char *pll_ve_parents[] = {"osc24M"}; +NMM_CLK(pll_ve_clk, + CLK_PLL_VE, /* id */ + "pll_ve", pll_ve_parents, /* name, parents */ + 0x58, /* offset */ + 8, 8, 0, 0, /* n factor */ + 0, 1, 0, 0, /* m0 factor */ + 1, 1, 0, 0, /* m1 factor */ + 31, /* gate */ + 28, 1000, /* lock */ + AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */ + +static const char *pll_de_parents[] = {"osc24M"}; +NMM_CLK(pll_de_clk, + CLK_PLL_DE, /* id */ + "pll_de", pll_de_parents, /* name, parents */ + 0x60, /* offset */ + 8, 8, 0, 0, /* n factor */ + 0, 1, 0, 0, /* m0 factor */ + 1, 1, 0, 0, /* m1 factor */ + 31, /* gate */ + 28, 1000, /* lock */ + AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */ + +/* PLL_AUDIO missing */ +// in h616 datasheet + +/* CPUX_AXI missing */ +// in h616 datasheet + +static const char *psi_ahb1_ahb2_parents[] = {"osc24M", "osc32k", "iosc", "pll_periph0"}; +NM_CLK(psi_ahb1_ahb2_clk, + CLK_PSI_AHB1_AHB2, "psi_ahb1_ahb2", psi_ahb1_ahb2_parents, /* id, name, parents */ + 0x510, /* offset */ + 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */ + 0, 2, 0, 0, /* m factor */ + 24, 2, /* mux */ + 0, /* gate */ + AW_CLK_HAS_MUX | AW_CLK_REPARENT); /* flags */ + +static const char *ahb3_parents[] = {"osc24M", "osc32k", "psi_ahb1_ahb2", "pll_periph0"}; +NM_CLK(ahb3_clk, + CLK_AHB3, "ahb3", ahb3_parents, /* id, name, parents */ + 0x51C, /* offset */ + 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */ + 0, 2, 0, 0, /* m factor */ + 24, 2, /* mux */ + 0, /* gate */ + AW_CLK_HAS_MUX | AW_CLK_REPARENT); /* flags */ + +static const char *apb1_parents[] = {"osc24M", "osc32k", "psi_ahb1_ahb2", "pll_periph0"}; +NM_CLK(apb1_clk, + CLK_APB1, "apb1", apb1_parents, /* id, name, parents */ + 0x520, /* offset */ + 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */ + 0, 2, 0, 0, /* m factor */ + 24, 2, /* mux */ + 0, /* gate */ + AW_CLK_HAS_MUX | AW_CLK_REPARENT); /* flags */ + +static const char *apb2_parents[] = {"osc24M", "osc32k", "psi_ahb1_ahb2", "pll_periph0"}; +NM_CLK(apb2_clk, + CLK_APB2, "apb2", apb2_parents, /* id, name, parents */ + 0x524, /* offset */ + 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */ + 0, 2, 0, 0, /* m factor */ + 24, 2, /* mux */ + 0, /* gate */ + AW_CLK_HAS_MUX | AW_CLK_REPARENT); /* flags */ + +/* Missing MBUS clock */ + +static const char *mod_parents[] = {"osc24M", "pll_periph0_2x", "pll_periph1_2x"}; +NM_CLK(mmc0_clk, + CLK_MMC0, "mmc0", mod_parents, /* id, name, parents */ + 0x830, /* offset */ + 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */ + 0, 4, 0, 0, /* m factor */ + 24, 2, /* mux */ + 31, /* gate */ + AW_CLK_HAS_GATE | AW_CLK_HAS_MUX | + AW_CLK_REPARENT); /* flags */ + +NM_CLK(mmc1_clk, + CLK_MMC1, "mmc1", mod_parents, /* id, name, parents */ + 0x834, /* offset */ + 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */ + 0, 4, 0, 0, /* m factor */ + 24, 2, /* mux */ + 31, /* gate */ + AW_CLK_HAS_GATE | AW_CLK_HAS_MUX | + AW_CLK_REPARENT); /* flags */ + +NM_CLK(mmc2_clk, + CLK_MMC2, "mmc2", mod_parents, /* id, name, parents */ + 0x838, /* offset */ + 8, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */ + 0, 4, 0, 0, /* m factor */ + 24, 2, /* mux */ + 31, /* gate */ + AW_CLK_HAS_GATE | AW_CLK_HAS_MUX | + AW_CLK_REPARENT); /* flags */ + +static struct aw_ccung_clk h616_ccu_clks[] = { + { .type = AW_CLK_NP, .clk.np = &pll_cpux_clk}, + { .type = AW_CLK_NMM, .clk.nmm = &pll_ddr0_clk}, + { .type = AW_CLK_NMM, .clk.nmm = &pll_ddr1_clk}, + { .type = AW_CLK_NMM, .clk.nmm = &pll_peri0_2x_clk}, + { .type = AW_CLK_NMM, .clk.nmm = &pll_peri1_2x_clk}, + { .type = AW_CLK_NMM, .clk.nmm = &pll_gpu_clk}, + { .type = AW_CLK_NMM, .clk.nmm = &pll_video0_4x_clk}, + { .type = AW_CLK_NMM, .clk.nmm = &pll_video1_4x_clk}, + { .type = AW_CLK_NMM, .clk.nmm = &pll_video2_4x_clk}, + { .type = AW_CLK_NMM, .clk.nmm = &pll_ve_clk}, + { .type = AW_CLK_NMM, .clk.nmm = &pll_de_clk}, + + { .type = AW_CLK_NM, .clk.nm = &psi_ahb1_ahb2_clk}, + { .type = AW_CLK_NM, .clk.nm = &ahb3_clk}, + { .type = AW_CLK_NM, .clk.nm = &apb1_clk}, + { .type = AW_CLK_NM, .clk.nm = &apb2_clk}, + + { .type = AW_CLK_NM, .clk.nm = &mmc0_clk}, + { .type = AW_CLK_NM, .clk.nm = &mmc1_clk}, + { .type = AW_CLK_NM, .clk.nm = &mmc2_clk}, + + { .type = AW_CLK_FIXED, .clk.fixed = &pll_peri0_clk}, + { .type = AW_CLK_FIXED, .clk.fixed = &pll_peri1_clk}, + { .type = AW_CLK_FIXED, .clk.fixed = &pll_video0_clk}, + { .type = AW_CLK_FIXED, .clk.fixed = &pll_video1_clk}, + { .type = AW_CLK_FIXED, .clk.fixed = &pll_video2_clk}, +}; + +static int +ccu_h616_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "allwinner,sun50i-h616-ccu")) + return (ENXIO); + + device_set_desc(dev, "Allwinner H616 Clock Control Unit"); + return (BUS_PROBE_DEFAULT); +} + +static int +ccu_h616_attach(device_t dev) +{ + struct aw_ccung_softc *sc; + + sc = device_get_softc(dev); + + sc->resets = h616_ccu_resets; + sc->nresets = nitems(h616_ccu_resets); + sc->gates = h616_ccu_gates; + sc->ngates = nitems(h616_ccu_gates); + sc->clks = h616_ccu_clks; + sc->nclks = nitems(h616_ccu_clks); + + return (aw_ccung_attach(dev)); +} + +static device_method_t ccu_h616ng_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ccu_h616_probe), + DEVMETHOD(device_attach, ccu_h616_attach), + + DEVMETHOD_END +}; + +DEFINE_CLASS_1(ccu_h616ng, ccu_h616ng_driver, ccu_h616ng_methods, + sizeof(struct aw_ccung_softc), aw_ccung_driver); + +EARLY_DRIVER_MODULE(ccu_h616ng, simplebus, ccu_h616ng_driver, 0, 0, + BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE); diff --git a/sys/dev/clk/clk_fixed.c b/sys/dev/clk/clk_fixed.c index f8dcfb8378cd..6656aeec473e 100644 --- a/sys/dev/clk/clk_fixed.c +++ b/sys/dev/clk/clk_fixed.c @@ -157,9 +157,11 @@ clk_fixed_probe(device_t dev) clk_type = ofw_bus_search_compatible(dev, compat_data)->ocd_data; switch (clk_type) { case CLK_TYPE_FIXED: - if (OF_hasprop(ofw_bus_get_node(dev), "clock-frequency") == 0) { - device_printf(dev, - "clock-fixed has no clock-frequency\n"); + if (!OF_hasprop(ofw_bus_get_node(dev), "clock-frequency")) { + if (bootverbose) { + device_printf(dev, + "clock-fixed has no clock-frequency\n"); + } return (ENXIO); } device_set_desc(dev, "Fixed clock"); diff --git a/sys/dev/clk/rockchip/rk_clk_fract.c b/sys/dev/clk/rockchip/rk_clk_fract.c index aa7084c90d76..b06b13146e5f 100644 --- a/sys/dev/clk/rockchip/rk_clk_fract.c +++ b/sys/dev/clk/rockchip/rk_clk_fract.c @@ -80,7 +80,7 @@ DEFINE_CLASS_1(rk_clk_fract, rk_clk_fract_class, rk_clk_fract_methods, * http://en.wikipedia.org/wiki/Continued_fraction * * - n_input, d_input Given input fraction - * - n_max, d_max Maximum vaues of divider registers + * - n_max, d_max Maximum values of divider registers * - n_out, d_out Computed approximation */ diff --git a/sys/dev/cxgb/cxgb_main.c b/sys/dev/cxgb/cxgb_main.c index 616a2ecc1a37..81fd3cb45841 100644 --- a/sys/dev/cxgb/cxgb_main.c +++ b/sys/dev/cxgb/cxgb_main.c @@ -187,7 +187,7 @@ static device_method_t cxgb_port_methods[] = { DEVMETHOD(device_probe, cxgb_port_probe), DEVMETHOD(device_attach, cxgb_port_attach), DEVMETHOD(device_detach, cxgb_port_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t cxgb_port_driver = { diff --git a/sys/dev/cxgbe/common/t4_hw.c b/sys/dev/cxgbe/common/t4_hw.c index 65292486cbc8..f4eef54e5c6b 100644 --- a/sys/dev/cxgbe/common/t4_hw.c +++ b/sys/dev/cxgbe/common/t4_hw.c @@ -3282,7 +3282,9 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size) 0x477d4, 0x477fc, 0x48000, 0x48004, 0x48018, 0x4801c, - 0x49304, 0x493f0, + 0x49304, 0x49320, + 0x4932c, 0x4932c, + 0x49334, 0x493f0, 0x49400, 0x49410, 0x49460, 0x494f4, 0x50000, 0x50084, @@ -3305,7 +3307,9 @@ void t4_get_regs(struct adapter *adap, u8 *buf, size_t buf_size) 0x515f0, 0x515f4, 0x58000, 0x58004, 0x58018, 0x5801c, - 0x59304, 0x593f0, + 0x59304, 0x59320, + 0x5932c, 0x5932c, + 0x59334, 0x593f0, 0x59400, 0x59410, 0x59460, 0x594f4, }; @@ -4793,7 +4797,6 @@ struct intr_info { static inline char intr_alert_char(u32 cause, u32 enable, u32 fatal) { - if (cause & fatal) return ('!'); if (cause & enable) @@ -4813,7 +4816,7 @@ show_intr_info(struct adapter *sc, const struct intr_info *ii, uint32_t cause, if (verbose || ucause != 0 || flags & IHF_RUN_ALL_ACTIONS) { alert = intr_alert_char(cause, enabled, fatal); CH_ALERT(sc, "%c %s 0x%x = 0x%08x, E 0x%08x, F 0x%08x\n", alert, - ii->name, ii->cause_reg, cause, enabled, fatal); + ii->name, ii->cause_reg, cause, enabled, ii->fatal); } leftover = verbose ? cause : ucause; @@ -4825,8 +4828,10 @@ show_intr_info(struct adapter *sc, const struct intr_info *ii, uint32_t cause, CH_ALERT(sc, " %c [0x%08x] %s\n", alert, msgbits, details->msg); leftover &= ~msgbits; } - if (leftover != 0 && leftover != (verbose ? cause : ucause)) - CH_ALERT(sc, " ? [0x%08x]\n", leftover); + if (leftover != 0 && leftover != (verbose ? cause : ucause)) { + alert = intr_alert_char(leftover, enabled, fatal); + CH_ALERT(sc, " %c [0x%08x]\n", alert, leftover); + } } /* @@ -6098,6 +6103,14 @@ static bool mem_intr_handler(struct adapter *adap, int idx, int flags) { F_PERR_INT_CAUSE, "FIFO parity error" }, { 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_T7_ECC_UE_INT_CAUSE, "Uncorrectable ECC data error(s)" }, + { F_PERR_INT_CAUSE, "FIFO parity error" }, + { 0 } + }; char rname[32]; struct intr_info ii = { .name = &rname[0], @@ -6152,6 +6165,8 @@ static bool mem_intr_handler(struct adapter *adap, int idx, int flags) } else { ii.cause_reg = MC_T7_REG(A_T7_MC_P_INT_CAUSE, i); 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); @@ -6177,11 +6192,6 @@ static bool mem_intr_handler(struct adapter *adap, int idx, int flags) 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); - - snprintf(rname, sizeof(rname), "MC%u_ECC_UE_INT_CAUSE", i); - ii.cause_reg = MC_T7_REG(A_MC_P_ECC_UE_INT_CAUSE, i); - ii.enable_reg = MC_T7_REG(A_MC_P_ECC_UE_INT_ENABLE, i); - fatal |= t4_handle_intr(adap, &ii, 0, flags); } break; } diff --git a/sys/dev/cxgbe/common/t4_regs.h b/sys/dev/cxgbe/common/t4_regs.h index 51f150443261..09d0d4aa2c08 100644 --- a/sys/dev/cxgbe/common/t4_regs.h +++ b/sys/dev/cxgbe/common/t4_regs.h @@ -27,11 +27,11 @@ */ /* This file is automatically generated --- changes will be lost */ -/* Generation Date : Tue Oct 28 05:23:45 PM IST 2025 */ +/* Generation Date : Thu Dec 11 08:42:50 PM IST 2025 */ /* Directory name: t4_reg.txt, Date: Not specified */ -/* Directory name: t5_reg.txt, Changeset: 6945:54ba4ba7ee8b */ +/* Directory name: t5_reg.txt, Changeset: 6946:9d3868c42009 */ /* Directory name: t6_reg.txt, Changeset: 4277:9c165d0f4899 */ -/* Directory name: t7_sw_reg.txt, Changeset: 5946:0b60ff298e7d */ +/* Directory name: t7_sw_reg.txt, Changeset: 5950:7c934148528c */ #define MYPF_BASE 0x1b000 #define MYPF_REG(reg_addr) (MYPF_BASE + (reg_addr)) @@ -6195,15 +6195,15 @@ #define A_PCIE_PF_INT_CFG 0x3140 -#define S_T7_VECNUM 12 -#define M_T7_VECNUM 0x7ffU -#define V_T7_VECNUM(x) ((x) << S_T7_VECNUM) -#define G_T7_VECNUM(x) (((x) >> S_T7_VECNUM) & M_T7_VECNUM) +#define S_T7_PF_INT_VECNUM 12 +#define M_T7_PF_INT_VECNUM 0x7ffU +#define V_T7_PF_INT_VECNUM(x) ((x) << S_T7_PF_INT_VECNUM) +#define G_T7_PF_INT_VECNUM(x) (((x) >> S_T7_PF_INT_VECNUM) & M_T7_PF_INT_VECNUM) -#define S_T7_VECBASE 0 -#define M_T7_VECBASE 0xfffU -#define V_T7_VECBASE(x) ((x) << S_T7_VECBASE) -#define G_T7_VECBASE(x) (((x) >> S_T7_VECBASE) & M_T7_VECBASE) +#define S_T7_PF_INT_VECBASE 0 +#define M_T7_PF_INT_VECBASE 0xfffU +#define V_T7_PF_INT_VECBASE(x) ((x) << S_T7_PF_INT_VECBASE) +#define G_T7_PF_INT_VECBASE(x) (((x) >> S_T7_PF_INT_VECBASE) & M_T7_PF_INT_VECBASE) #define A_PCIE_PF_INT_CFG2 0x3144 #define A_PCIE_VF_INT_CFG 0x3180 @@ -10636,6 +10636,12 @@ #define G_VFID_PCIE(x) (((x) >> S_VFID_PCIE) & M_VFID_PCIE) #define A_PCIE_VF_INT_INDIR_DATA 0x5c48 + +#define S_T7_VECBASE 0 +#define M_T7_VECBASE 0xfffU +#define V_T7_VECBASE(x) ((x) << S_T7_VECBASE) +#define G_T7_VECBASE(x) (((x) >> S_T7_VECBASE) & M_T7_VECBASE) + #define A_PCIE_VF_256_INT_CFG2 0x5c4c #define A_PCIE_VF_MSI_EN_4 0x5e50 #define A_PCIE_VF_MSI_EN_5 0x5e54 @@ -17723,6 +17729,22 @@ #define V_GPIO20_PE_EN(x) ((x) << S_GPIO20_PE_EN) #define F_GPIO20_PE_EN V_GPIO20_PE_EN(1U) +#define S_T7_GPIO19_PE_EN 19 +#define V_T7_GPIO19_PE_EN(x) ((x) << S_T7_GPIO19_PE_EN) +#define F_T7_GPIO19_PE_EN V_T7_GPIO19_PE_EN(1U) + +#define S_T7_GPIO18_PE_EN 18 +#define V_T7_GPIO18_PE_EN(x) ((x) << S_T7_GPIO18_PE_EN) +#define F_T7_GPIO18_PE_EN V_T7_GPIO18_PE_EN(1U) + +#define S_T7_GPIO17_PE_EN 17 +#define V_T7_GPIO17_PE_EN(x) ((x) << S_T7_GPIO17_PE_EN) +#define F_T7_GPIO17_PE_EN V_T7_GPIO17_PE_EN(1U) + +#define S_T7_GPIO16_PE_EN 16 +#define V_T7_GPIO16_PE_EN(x) ((x) << S_T7_GPIO16_PE_EN) +#define F_T7_GPIO16_PE_EN V_T7_GPIO16_PE_EN(1U) + #define A_DBG_PVT_REG_THRESHOLD 0x611c #define S_PVT_CALIBRATION_DONE 8 @@ -17859,6 +17881,22 @@ #define V_GPIO20_PS_EN(x) ((x) << S_GPIO20_PS_EN) #define F_GPIO20_PS_EN V_GPIO20_PS_EN(1U) +#define S_T7_GPIO19_PS_EN 19 +#define V_T7_GPIO19_PS_EN(x) ((x) << S_T7_GPIO19_PS_EN) +#define F_T7_GPIO19_PS_EN V_T7_GPIO19_PS_EN(1U) + +#define S_T7_GPIO18_PS_EN 18 +#define V_T7_GPIO18_PS_EN(x) ((x) << S_T7_GPIO18_PS_EN) +#define F_T7_GPIO18_PS_EN V_T7_GPIO18_PS_EN(1U) + +#define S_T7_GPIO17_PS_EN 17 +#define V_T7_GPIO17_PS_EN(x) ((x) << S_T7_GPIO17_PS_EN) +#define F_T7_GPIO17_PS_EN V_T7_GPIO17_PS_EN(1U) + +#define S_T7_GPIO16_PS_EN 16 +#define V_T7_GPIO16_PS_EN(x) ((x) << S_T7_GPIO16_PS_EN) +#define F_T7_GPIO16_PS_EN V_T7_GPIO16_PS_EN(1U) + #define A_DBG_PVT_REG_IN_TERMP 0x6120 #define S_REG_IN_TERMP_B 4 @@ -21825,10 +21863,6 @@ #define V_FUTURE_DEXPANSION_WTS(x) ((x) << S_FUTURE_DEXPANSION_WTS) #define G_FUTURE_DEXPANSION_WTS(x) (((x) >> S_FUTURE_DEXPANSION_WTS) & M_FUTURE_DEXPANSION_WTS) -#define S_T7_FUTURE_CEXPANSION_WTS 31 -#define V_T7_FUTURE_CEXPANSION_WTS(x) ((x) << S_T7_FUTURE_CEXPANSION_WTS) -#define F_T7_FUTURE_CEXPANSION_WTS V_T7_FUTURE_CEXPANSION_WTS(1U) - #define S_CL14_WR_CMD_TO_ERROR 30 #define V_CL14_WR_CMD_TO_ERROR(x) ((x) << S_CL14_WR_CMD_TO_ERROR) #define F_CL14_WR_CMD_TO_ERROR V_CL14_WR_CMD_TO_ERROR(1U) @@ -21837,10 +21871,6 @@ #define V_CL13_WR_CMD_TO_ERROR(x) ((x) << S_CL13_WR_CMD_TO_ERROR) #define F_CL13_WR_CMD_TO_ERROR V_CL13_WR_CMD_TO_ERROR(1U) -#define S_T7_FUTURE_DEXPANSION_WTS 15 -#define V_T7_FUTURE_DEXPANSION_WTS(x) ((x) << S_T7_FUTURE_DEXPANSION_WTS) -#define F_T7_FUTURE_DEXPANSION_WTS V_T7_FUTURE_DEXPANSION_WTS(1U) - #define S_CL14_WR_DATA_TO_ERROR 14 #define V_CL14_WR_DATA_TO_ERROR(x) ((x) << S_CL14_WR_DATA_TO_ERROR) #define F_CL14_WR_DATA_TO_ERROR V_CL14_WR_DATA_TO_ERROR(1U) @@ -21965,10 +21995,6 @@ #define V_FUTURE_DEXPANSION_RTE(x) ((x) << S_FUTURE_DEXPANSION_RTE) #define G_FUTURE_DEXPANSION_RTE(x) (((x) >> S_FUTURE_DEXPANSION_RTE) & M_FUTURE_DEXPANSION_RTE) -#define S_T7_FUTURE_CEXPANSION_RTE 31 -#define V_T7_FUTURE_CEXPANSION_RTE(x) ((x) << S_T7_FUTURE_CEXPANSION_RTE) -#define F_T7_FUTURE_CEXPANSION_RTE V_T7_FUTURE_CEXPANSION_RTE(1U) - #define S_CL14_RD_CMD_TO_EN 30 #define V_CL14_RD_CMD_TO_EN(x) ((x) << S_CL14_RD_CMD_TO_EN) #define F_CL14_RD_CMD_TO_EN V_CL14_RD_CMD_TO_EN(1U) @@ -21977,10 +22003,6 @@ #define V_CL13_RD_CMD_TO_EN(x) ((x) << S_CL13_RD_CMD_TO_EN) #define F_CL13_RD_CMD_TO_EN V_CL13_RD_CMD_TO_EN(1U) -#define S_T7_FUTURE_DEXPANSION_RTE 15 -#define V_T7_FUTURE_DEXPANSION_RTE(x) ((x) << S_T7_FUTURE_DEXPANSION_RTE) -#define F_T7_FUTURE_DEXPANSION_RTE V_T7_FUTURE_DEXPANSION_RTE(1U) - #define S_CL14_RD_DATA_TO_EN 14 #define V_CL14_RD_DATA_TO_EN(x) ((x) << S_CL14_RD_DATA_TO_EN) #define F_CL14_RD_DATA_TO_EN V_CL14_RD_DATA_TO_EN(1U) @@ -22105,10 +22127,6 @@ #define V_FUTURE_DEXPANSION_RTS(x) ((x) << S_FUTURE_DEXPANSION_RTS) #define G_FUTURE_DEXPANSION_RTS(x) (((x) >> S_FUTURE_DEXPANSION_RTS) & M_FUTURE_DEXPANSION_RTS) -#define S_T7_FUTURE_CEXPANSION_RTS 31 -#define V_T7_FUTURE_CEXPANSION_RTS(x) ((x) << S_T7_FUTURE_CEXPANSION_RTS) -#define F_T7_FUTURE_CEXPANSION_RTS V_T7_FUTURE_CEXPANSION_RTS(1U) - #define S_CL14_RD_CMD_TO_ERROR 30 #define V_CL14_RD_CMD_TO_ERROR(x) ((x) << S_CL14_RD_CMD_TO_ERROR) #define F_CL14_RD_CMD_TO_ERROR V_CL14_RD_CMD_TO_ERROR(1U) @@ -22117,10 +22135,9 @@ #define V_CL13_RD_CMD_TO_ERROR(x) ((x) << S_CL13_RD_CMD_TO_ERROR) #define F_CL13_RD_CMD_TO_ERROR V_CL13_RD_CMD_TO_ERROR(1U) -#define S_T7_FUTURE_DEXPANSION_RTS 14 -#define M_T7_FUTURE_DEXPANSION_RTS 0x3U -#define V_T7_FUTURE_DEXPANSION_RTS(x) ((x) << S_T7_FUTURE_DEXPANSION_RTS) -#define G_T7_FUTURE_DEXPANSION_RTS(x) (((x) >> S_T7_FUTURE_DEXPANSION_RTS) & M_T7_FUTURE_DEXPANSION_RTS) +#define S_CL14_RD_DATA_TO_ERROR 14 +#define V_CL14_RD_DATA_TO_ERROR(x) ((x) << S_CL14_RD_DATA_TO_ERROR) +#define F_CL14_RD_DATA_TO_ERROR V_CL14_RD_DATA_TO_ERROR(1U) #define S_CL13_RD_DATA_TO_ERROR 13 #define V_CL13_RD_DATA_TO_ERROR(x) ((x) << S_CL13_RD_DATA_TO_ERROR) @@ -22224,10 +22241,9 @@ #define V_FUTURE_DEXPANSION_IPE(x) ((x) << S_FUTURE_DEXPANSION_IPE) #define G_FUTURE_DEXPANSION_IPE(x) (((x) >> S_FUTURE_DEXPANSION_IPE) & M_FUTURE_DEXPANSION_IPE) -#define S_T7_FUTURE_DEXPANSION_IPE 14 -#define M_T7_FUTURE_DEXPANSION_IPE 0x3ffffU -#define V_T7_FUTURE_DEXPANSION_IPE(x) ((x) << S_T7_FUTURE_DEXPANSION_IPE) -#define G_T7_FUTURE_DEXPANSION_IPE(x) (((x) >> S_T7_FUTURE_DEXPANSION_IPE) & M_T7_FUTURE_DEXPANSION_IPE) +#define S_CL14_IF_PAR_EN 14 +#define V_CL14_IF_PAR_EN(x) ((x) << S_CL14_IF_PAR_EN) +#define F_CL14_IF_PAR_EN V_CL14_IF_PAR_EN(1U) #define S_CL13_IF_PAR_EN 13 #define V_CL13_IF_PAR_EN(x) ((x) << S_CL13_IF_PAR_EN) @@ -22292,10 +22308,9 @@ #define V_FUTURE_DEXPANSION_IPS(x) ((x) << S_FUTURE_DEXPANSION_IPS) #define G_FUTURE_DEXPANSION_IPS(x) (((x) >> S_FUTURE_DEXPANSION_IPS) & M_FUTURE_DEXPANSION_IPS) -#define S_T7_FUTURE_DEXPANSION_IPS 14 -#define M_T7_FUTURE_DEXPANSION_IPS 0x3ffffU -#define V_T7_FUTURE_DEXPANSION_IPS(x) ((x) << S_T7_FUTURE_DEXPANSION_IPS) -#define G_T7_FUTURE_DEXPANSION_IPS(x) (((x) >> S_T7_FUTURE_DEXPANSION_IPS) & M_T7_FUTURE_DEXPANSION_IPS) +#define S_CL14_IF_PAR_ERROR 14 +#define V_CL14_IF_PAR_ERROR(x) ((x) << S_CL14_IF_PAR_ERROR) +#define F_CL14_IF_PAR_ERROR V_CL14_IF_PAR_ERROR(1U) #define S_CL13_IF_PAR_ERROR 13 #define V_CL13_IF_PAR_ERROR(x) ((x) << S_CL13_IF_PAR_ERROR) @@ -39030,21 +39045,21 @@ #define A_PM_TX_CH1_OSPI_DEFICIT_THRSHLD 0x10028 #define A_PM_TX_PERR_ENABLE 0x10028 -#define S_T7_1_OSPI_OVERFLOW3 23 -#define V_T7_1_OSPI_OVERFLOW3(x) ((x) << S_T7_1_OSPI_OVERFLOW3) -#define F_T7_1_OSPI_OVERFLOW3 V_T7_1_OSPI_OVERFLOW3(1U) +#define S_OSPI_OVERFLOW3_TX 23 +#define V_OSPI_OVERFLOW3_TX(x) ((x) << S_OSPI_OVERFLOW3_TX) +#define F_OSPI_OVERFLOW3_TX V_OSPI_OVERFLOW3_TX(1U) -#define S_T7_1_OSPI_OVERFLOW2 22 -#define V_T7_1_OSPI_OVERFLOW2(x) ((x) << S_T7_1_OSPI_OVERFLOW2) -#define F_T7_1_OSPI_OVERFLOW2 V_T7_1_OSPI_OVERFLOW2(1U) +#define S_OSPI_OVERFLOW2_TX 22 +#define V_OSPI_OVERFLOW2_TX(x) ((x) << S_OSPI_OVERFLOW2_TX) +#define F_OSPI_OVERFLOW2_TX V_OSPI_OVERFLOW2_TX(1U) -#define S_T7_1_OSPI_OVERFLOW1 21 -#define V_T7_1_OSPI_OVERFLOW1(x) ((x) << S_T7_1_OSPI_OVERFLOW1) -#define F_T7_1_OSPI_OVERFLOW1 V_T7_1_OSPI_OVERFLOW1(1U) +#define S_OSPI_OVERFLOW1_TX 21 +#define V_OSPI_OVERFLOW1_TX(x) ((x) << S_OSPI_OVERFLOW1_TX) +#define F_OSPI_OVERFLOW1_TX V_OSPI_OVERFLOW1_TX(1U) -#define S_T7_1_OSPI_OVERFLOW0 20 -#define V_T7_1_OSPI_OVERFLOW0(x) ((x) << S_T7_1_OSPI_OVERFLOW0) -#define F_T7_1_OSPI_OVERFLOW0 V_T7_1_OSPI_OVERFLOW0(1U) +#define S_OSPI_OVERFLOW0_TX 20 +#define V_OSPI_OVERFLOW0_TX(x) ((x) << S_OSPI_OVERFLOW0_TX) +#define F_OSPI_OVERFLOW0_TX V_OSPI_OVERFLOW0_TX(1U) #define S_T7_BUNDLE_LEN_OVFL_EN 18 #define V_T7_BUNDLE_LEN_OVFL_EN(x) ((x) << S_T7_BUNDLE_LEN_OVFL_EN) @@ -41390,15 +41405,65 @@ #define V_T7_BUBBLE(x) ((x) << S_T7_BUBBLE) #define F_T7_BUBBLE V_T7_BUBBLE(1U) -#define S_TXTOKENFIFO 15 -#define M_TXTOKENFIFO 0x3ffU -#define V_TXTOKENFIFO(x) ((x) << S_TXTOKENFIFO) -#define G_TXTOKENFIFO(x) (((x) >> S_TXTOKENFIFO) & M_TXTOKENFIFO) +#define S_TX_TF_FIFO_PERR 19 +#define V_TX_TF_FIFO_PERR(x) ((x) << S_TX_TF_FIFO_PERR) +#define F_TX_TF_FIFO_PERR V_TX_TF_FIFO_PERR(1U) -#define S_PERR_TP2MPS_TFIFO 13 -#define M_PERR_TP2MPS_TFIFO 0x3U -#define V_PERR_TP2MPS_TFIFO(x) ((x) << S_PERR_TP2MPS_TFIFO) -#define G_PERR_TP2MPS_TFIFO(x) (((x) >> S_PERR_TP2MPS_TFIFO) & M_PERR_TP2MPS_TFIFO) +#define S_TX_FIFO_PERR 18 +#define V_TX_FIFO_PERR(x) ((x) << S_TX_FIFO_PERR) +#define F_TX_FIFO_PERR V_TX_FIFO_PERR(1U) + +#define S_NON_IPSEC_TX_FIFO3_PERR 17 +#define V_NON_IPSEC_TX_FIFO3_PERR(x) ((x) << S_NON_IPSEC_TX_FIFO3_PERR) +#define F_NON_IPSEC_TX_FIFO3_PERR V_NON_IPSEC_TX_FIFO3_PERR(1U) + +#define S_NON_IPSEC_TX_FIFO2_PERR 16 +#define V_NON_IPSEC_TX_FIFO2_PERR(x) ((x) << S_NON_IPSEC_TX_FIFO2_PERR) +#define F_NON_IPSEC_TX_FIFO2_PERR V_NON_IPSEC_TX_FIFO2_PERR(1U) + +#define S_NON_IPSEC_TX_FIFO1_PERR 15 +#define V_NON_IPSEC_TX_FIFO1_PERR(x) ((x) << S_NON_IPSEC_TX_FIFO1_PERR) +#define F_NON_IPSEC_TX_FIFO1_PERR V_NON_IPSEC_TX_FIFO1_PERR(1U) + +#define S_NON_IPSEC_TX_FIFO0_PERR 14 +#define V_NON_IPSEC_TX_FIFO0_PERR(x) ((x) << S_NON_IPSEC_TX_FIFO0_PERR) +#define F_NON_IPSEC_TX_FIFO0_PERR V_NON_IPSEC_TX_FIFO0_PERR(1U) + +#define S_TP2MPS_TX0 13 +#define V_TP2MPS_TX0(x) ((x) << S_TP2MPS_TX0) +#define F_TP2MPS_TX0 V_TP2MPS_TX0(1U) + +#define S_CRYPTO2MPS_TX0 12 +#define V_CRYPTO2MPS_TX0(x) ((x) << S_CRYPTO2MPS_TX0) +#define F_CRYPTO2MPS_TX0 V_CRYPTO2MPS_TX0(1U) + +#define S_TP2MPS_TX1 11 +#define V_TP2MPS_TX1(x) ((x) << S_TP2MPS_TX1) +#define F_TP2MPS_TX1 V_TP2MPS_TX1(1U) + +#define S_CRYPTO2MPS_TX1 10 +#define V_CRYPTO2MPS_TX1(x) ((x) << S_CRYPTO2MPS_TX1) +#define F_CRYPTO2MPS_TX1 V_CRYPTO2MPS_TX1(1U) + +#define S_TP2MPS_TX2 9 +#define V_TP2MPS_TX2(x) ((x) << S_TP2MPS_TX2) +#define F_TP2MPS_TX2 V_TP2MPS_TX2(1U) + +#define S_CRYPTO2MPS_TX2 8 +#define V_CRYPTO2MPS_TX2(x) ((x) << S_CRYPTO2MPS_TX2) +#define F_CRYPTO2MPS_TX2 V_CRYPTO2MPS_TX2(1U) + +#define S_TP2MPS_TX3 7 +#define V_TP2MPS_TX3(x) ((x) << S_TP2MPS_TX3) +#define F_TP2MPS_TX3 V_TP2MPS_TX3(1U) + +#define S_CRYPTO2MPS_TX3 6 +#define V_CRYPTO2MPS_TX3(x) ((x) << S_CRYPTO2MPS_TX3) +#define F_CRYPTO2MPS_TX3 V_CRYPTO2MPS_TX3(1U) + +#define S_NCSI2MPS 5 +#define V_NCSI2MPS(x) ((x) << S_NCSI2MPS) +#define F_NCSI2MPS V_NCSI2MPS(1U) #define A_MPS_TX_INT_CAUSE 0x9408 #define A_MPS_TX_NCSI2MPS_CNT 0x940c @@ -41420,6 +41485,16 @@ #define V_BUBBLEERRINT(x) ((x) << S_BUBBLEERRINT) #define F_BUBBLEERRINT V_BUBBLEERRINT(1U) +#define S_TXTOKENFIFO 15 +#define M_TXTOKENFIFO 0x3ffU +#define V_TXTOKENFIFO(x) ((x) << S_TXTOKENFIFO) +#define G_TXTOKENFIFO(x) (((x) >> S_TXTOKENFIFO) & M_TXTOKENFIFO) + +#define S_PERR_TP2MPS_TFIFO 13 +#define M_PERR_TP2MPS_TFIFO 0x3U +#define V_PERR_TP2MPS_TFIFO(x) ((x) << S_PERR_TP2MPS_TFIFO) +#define G_PERR_TP2MPS_TFIFO(x) (((x) >> S_PERR_TP2MPS_TFIFO) & M_PERR_TP2MPS_TFIFO) + #define A_MPS_TX_PERR_INJECT 0x9414 #define S_MPSTXMEMSEL 1 @@ -42174,7 +42249,45 @@ #define A_MPS_TX_DBG_CNT 0x947c #define A_MPS_TX_INT2_ENABLE 0x9498 + +#define S_T7_TX_FIFO_PERR 4 +#define V_T7_TX_FIFO_PERR(x) ((x) << S_T7_TX_FIFO_PERR) +#define F_T7_TX_FIFO_PERR V_T7_TX_FIFO_PERR(1U) + +#define S_NON_IPSEC_TX_FIFO3 3 +#define V_NON_IPSEC_TX_FIFO3(x) ((x) << S_NON_IPSEC_TX_FIFO3) +#define F_NON_IPSEC_TX_FIFO3 V_NON_IPSEC_TX_FIFO3(1U) + +#define S_NON_IPSEC_TX_FIFO2 2 +#define V_NON_IPSEC_TX_FIFO2(x) ((x) << S_NON_IPSEC_TX_FIFO2) +#define F_NON_IPSEC_TX_FIFO2 V_NON_IPSEC_TX_FIFO2(1U) + +#define S_NON_IPSEC_TX_FIFO1 1 +#define V_NON_IPSEC_TX_FIFO1(x) ((x) << S_NON_IPSEC_TX_FIFO1) +#define F_NON_IPSEC_TX_FIFO1 V_NON_IPSEC_TX_FIFO1(1U) + +#define S_NON_IPSEC_TX_FIFO0 0 +#define V_NON_IPSEC_TX_FIFO0(x) ((x) << S_NON_IPSEC_TX_FIFO0) +#define F_NON_IPSEC_TX_FIFO0 V_NON_IPSEC_TX_FIFO0(1U) + #define A_MPS_TX_INT2_CAUSE 0x949c + +#define S_T7_NON_IPSEC_TX_FIFO3_PERR 3 +#define V_T7_NON_IPSEC_TX_FIFO3_PERR(x) ((x) << S_T7_NON_IPSEC_TX_FIFO3_PERR) +#define F_T7_NON_IPSEC_TX_FIFO3_PERR V_T7_NON_IPSEC_TX_FIFO3_PERR(1U) + +#define S_T7_NON_IPSEC_TX_FIFO2_PERR 2 +#define V_T7_NON_IPSEC_TX_FIFO2_PERR(x) ((x) << S_T7_NON_IPSEC_TX_FIFO2_PERR) +#define F_T7_NON_IPSEC_TX_FIFO2_PERR V_T7_NON_IPSEC_TX_FIFO2_PERR(1U) + +#define S_T7_NON_IPSEC_TX_FIFO1_PERR 1 +#define V_T7_NON_IPSEC_TX_FIFO1_PERR(x) ((x) << S_T7_NON_IPSEC_TX_FIFO1_PERR) +#define F_T7_NON_IPSEC_TX_FIFO1_PERR V_T7_NON_IPSEC_TX_FIFO1_PERR(1U) + +#define S_T7_NON_IPSEC_TX_FIFO0_PERR 0 +#define V_T7_NON_IPSEC_TX_FIFO0_PERR(x) ((x) << S_T7_NON_IPSEC_TX_FIFO0_PERR) +#define F_T7_NON_IPSEC_TX_FIFO0_PERR V_T7_NON_IPSEC_TX_FIFO0_PERR(1U) + #define A_MPS_TX_PERR2_ENABLE 0x94a0 #define A_MPS_TX_INT3_ENABLE 0x94a4 #define A_MPS_TX_INT3_CAUSE 0x94a8 @@ -42307,6 +42420,12 @@ #define G_T5_TXPORT(x) (((x) >> S_T5_TXPORT) & M_T5_TXPORT) #define A_MPS_STAT_PERR_INT_CAUSE_SRAM 0x9614 + +#define S_T5_RXPP 29 +#define M_T5_RXPP 0x3U +#define V_T5_RXPP(x) ((x) << S_T5_RXPP) +#define G_T5_RXPP(x) (((x) >> S_T5_RXPP) & M_T5_RXPP) + #define A_MPS_STAT_PERR_ENABLE_SRAM 0x9618 #define A_MPS_STAT_PERR_INT_ENABLE_TX_FIFO 0x961c @@ -42429,6 +42548,26 @@ #define V_T5_TXVF(x) ((x) << S_T5_TXVF) #define G_T5_TXVF(x) (((x) >> S_T5_TXVF) & M_T5_TXVF) +#define S_RXVF_CERR 12 +#define M_RXVF_CERR 0xfU +#define V_RXVF_CERR(x) ((x) << S_RXVF_CERR) +#define G_RXVF_CERR(x) (((x) >> S_RXVF_CERR) & M_RXVF_CERR) + +#define S_TXVF_CERR 8 +#define M_TXVF_CERR 0xfU +#define V_TXVF_CERR(x) ((x) << S_TXVF_CERR) +#define G_TXVF_CERR(x) (((x) >> S_TXVF_CERR) & M_TXVF_CERR) + +#define S_RXVF_PERR 5 +#define M_RXVF_PERR 0x7U +#define V_RXVF_PERR(x) ((x) << S_RXVF_PERR) +#define G_RXVF_PERR(x) (((x) >> S_RXVF_PERR) & M_RXVF_PERR) + +#define S_TXVF_PERR 0 +#define M_TXVF_PERR 0x1fU +#define V_TXVF_PERR(x) ((x) << S_TXVF_PERR) +#define G_TXVF_PERR(x) (((x) >> S_TXVF_PERR) & M_TXVF_PERR) + #define A_MPS_STAT_PERR_INT_CAUSE_SRAM1 0x96c4 #define A_MPS_STAT_PERR_ENABLE_SRAM1 0x96c8 #define A_MPS_STAT_STOP_UPD_BG 0x96cc @@ -42641,6 +42780,10 @@ #define V_FILTMEM(x) ((x) << S_FILTMEM) #define G_FILTMEM(x) (((x) >> S_FILTMEM) & M_FILTMEM) +#define S_T7_TRCPLERRENB 17 +#define V_T7_TRCPLERRENB(x) ((x) << S_T7_TRCPLERRENB) +#define F_T7_TRCPLERRENB V_T7_TRCPLERRENB(1U) + #define S_T7_MISCPERR 16 #define V_T7_MISCPERR(x) ((x) << S_T7_MISCPERR) #define F_T7_MISCPERR V_T7_MISCPERR(1U) @@ -42814,11 +42957,6 @@ #define A_T7_MPS_TRC_FILTER_RUNT_CTL 0xa4a0 #define A_T7_MPS_TRC_FILTER_DROP 0xa4c0 #define A_T7_MPS_TRC_INT_ENABLE 0xa4e0 - -#define S_T7_TRCPLERRENB 17 -#define V_T7_TRCPLERRENB(x) ((x) << S_T7_TRCPLERRENB) -#define F_T7_TRCPLERRENB V_T7_TRCPLERRENB(1U) - #define A_T7_MPS_TRC_INT_CAUSE 0xa4e4 #define A_T7_MPS_TRC_TIMESTAMP_L 0xa4e8 #define A_T7_MPS_TRC_TIMESTAMP_H 0xa4ec @@ -42885,13 +43023,72 @@ #define G_PERR_TF_IN_CTL(x) (((x) >> S_PERR_TF_IN_CTL) & M_PERR_TF_IN_CTL) #define A_MPS_TRC_INT_ENABLE2 0xa4f4 -#define A_MPS_TRC_INT_CAUSE2 0xa4f8 -#define S_T7_TRC_TF_ECC 22 -#define M_T7_TRC_TF_ECC 0xffU -#define V_T7_TRC_TF_ECC(x) ((x) << S_T7_TRC_TF_ECC) -#define G_T7_TRC_TF_ECC(x) (((x) >> S_T7_TRC_TF_ECC) & M_T7_TRC_TF_ECC) +#define S_TX2RX_DWN_CONV_PERR_PT3_CERR 16 +#define V_TX2RX_DWN_CONV_PERR_PT3_CERR(x) ((x) << S_TX2RX_DWN_CONV_PERR_PT3_CERR) +#define F_TX2RX_DWN_CONV_PERR_PT3_CERR V_TX2RX_DWN_CONV_PERR_PT3_CERR(1U) + +#define S_TX2RX_DWN_CONV_PERR_PT2_CERR 15 +#define V_TX2RX_DWN_CONV_PERR_PT2_CERR(x) ((x) << S_TX2RX_DWN_CONV_PERR_PT2_CERR) +#define F_TX2RX_DWN_CONV_PERR_PT2_CERR V_TX2RX_DWN_CONV_PERR_PT2_CERR(1U) + +#define S_TX2RX_DWN_CONV_PERR_PT1_CERR 14 +#define V_TX2RX_DWN_CONV_PERR_PT1_CERR(x) ((x) << S_TX2RX_DWN_CONV_PERR_PT1_CERR) +#define F_TX2RX_DWN_CONV_PERR_PT1_CERR V_TX2RX_DWN_CONV_PERR_PT1_CERR(1U) + +#define S_TX2RX_DWN_CONV_PERR_PT0_CERR 13 +#define V_TX2RX_DWN_CONV_PERR_PT0_CERR(x) ((x) << S_TX2RX_DWN_CONV_PERR_PT0_CERR) +#define F_TX2RX_DWN_CONV_PERR_PT0_CERR V_TX2RX_DWN_CONV_PERR_PT0_CERR(1U) +#define S_MPS2MAC_DWN_CONV_PERR_PT1_CERR 12 +#define V_MPS2MAC_DWN_CONV_PERR_PT1_CERR(x) ((x) << S_MPS2MAC_DWN_CONV_PERR_PT1_CERR) +#define F_MPS2MAC_DWN_CONV_PERR_PT1_CERR V_MPS2MAC_DWN_CONV_PERR_PT1_CERR(1U) + +#define S_MPS2MAC_DWN_CONV_PERR_PT0_CERR 11 +#define V_MPS2MAC_DWN_CONV_PERR_PT0_CERR(x) ((x) << S_MPS2MAC_DWN_CONV_PERR_PT0_CERR) +#define F_MPS2MAC_DWN_CONV_PERR_PT0_CERR V_MPS2MAC_DWN_CONV_PERR_PT0_CERR(1U) + +#define S_MAC2MPS_DWN_CONV_PERR_PT1_CERR 10 +#define V_MAC2MPS_DWN_CONV_PERR_PT1_CERR(x) ((x) << S_MAC2MPS_DWN_CONV_PERR_PT1_CERR) +#define F_MAC2MPS_DWN_CONV_PERR_PT1_CERR V_MAC2MPS_DWN_CONV_PERR_PT1_CERR(1U) + +#define S_MAC2MPS_DWN_CONV_PERR_PT0_CERR 9 +#define V_MAC2MPS_DWN_CONV_PERR_PT0_CERR(x) ((x) << S_MAC2MPS_DWN_CONV_PERR_PT0_CERR) +#define F_MAC2MPS_DWN_CONV_PERR_PT0_CERR V_MAC2MPS_DWN_CONV_PERR_PT0_CERR(1U) + +#define S_TX2RX_DWN_CONV_PERR_PT3_PERR 8 +#define V_TX2RX_DWN_CONV_PERR_PT3_PERR(x) ((x) << S_TX2RX_DWN_CONV_PERR_PT3_PERR) +#define F_TX2RX_DWN_CONV_PERR_PT3_PERR V_TX2RX_DWN_CONV_PERR_PT3_PERR(1U) + +#define S_TX2RX_DWN_CONV_PERR_PT2_PERR 7 +#define V_TX2RX_DWN_CONV_PERR_PT2_PERR(x) ((x) << S_TX2RX_DWN_CONV_PERR_PT2_PERR) +#define F_TX2RX_DWN_CONV_PERR_PT2_PERR V_TX2RX_DWN_CONV_PERR_PT2_PERR(1U) + +#define S_TX2RX_DWN_CONV_PERR_PT1_PERR 6 +#define V_TX2RX_DWN_CONV_PERR_PT1_PERR(x) ((x) << S_TX2RX_DWN_CONV_PERR_PT1_PERR) +#define F_TX2RX_DWN_CONV_PERR_PT1_PERR V_TX2RX_DWN_CONV_PERR_PT1_PERR(1U) + +#define S_TX2RX_DWN_CONV_PERR_PT0_PERR 5 +#define V_TX2RX_DWN_CONV_PERR_PT0_PERR(x) ((x) << S_TX2RX_DWN_CONV_PERR_PT0_PERR) +#define F_TX2RX_DWN_CONV_PERR_PT0_PERR V_TX2RX_DWN_CONV_PERR_PT0_PERR(1U) + +#define S_MAC2MPS_DWN_CONV_PERR_PT1_PERR 4 +#define V_MAC2MPS_DWN_CONV_PERR_PT1_PERR(x) ((x) << S_MAC2MPS_DWN_CONV_PERR_PT1_PERR) +#define F_MAC2MPS_DWN_CONV_PERR_PT1_PERR V_MAC2MPS_DWN_CONV_PERR_PT1_PERR(1U) + +#define S_MAC2MPS_DWN_CONV_PERR_PT0_PERR 3 +#define V_MAC2MPS_DWN_CONV_PERR_PT0_PERR(x) ((x) << S_MAC2MPS_DWN_CONV_PERR_PT0_PERR) +#define F_MAC2MPS_DWN_CONV_PERR_PT0_PERR V_MAC2MPS_DWN_CONV_PERR_PT0_PERR(1U) + +#define S_MPS2MAC_DWN_CONV_PERR_PT1_PERR 2 +#define V_MPS2MAC_DWN_CONV_PERR_PT1_PERR(x) ((x) << S_MPS2MAC_DWN_CONV_PERR_PT1_PERR) +#define F_MPS2MAC_DWN_CONV_PERR_PT1_PERR V_MPS2MAC_DWN_CONV_PERR_PT1_PERR(1U) + +#define S_MPS2MAC_DWN_CONV_PERR_PT0_PERR 1 +#define V_MPS2MAC_DWN_CONV_PERR_PT0_PERR(x) ((x) << S_MPS2MAC_DWN_CONV_PERR_PT0_PERR) +#define F_MPS2MAC_DWN_CONV_PERR_PT0_PERR V_MPS2MAC_DWN_CONV_PERR_PT0_PERR(1U) + +#define A_MPS_TRC_INT_CAUSE2 0xa4f8 #define A_MPS_CLS_CTL 0xd000 #define S_MEMWRITEFAULT 4 @@ -43743,9 +43940,9 @@ #define A_MPS_RX_CHMN_CNT 0x11070 #define A_MPS_CTL_STAT 0x11070 -#define S_T7_CTL 0 -#define V_T7_CTL(x) ((x) << S_T7_CTL) -#define F_T7_CTL V_T7_CTL(1U) +#define S_T7_MPS_CTL 0 +#define V_T7_MPS_CTL(x) ((x) << S_T7_MPS_CTL) +#define F_T7_MPS_CTL V_T7_MPS_CTL(1U) #define A_MPS_RX_PERR_INT_CAUSE 0x11074 @@ -43849,54 +44046,60 @@ #define V_T6_INT_ERR_INT(x) ((x) << S_T6_INT_ERR_INT) #define F_T6_INT_ERR_INT V_T6_INT_ERR_INT(1U) -#define S_MAC_IN_FIFO_768B 30 -#define V_MAC_IN_FIFO_768B(x) ((x) << S_MAC_IN_FIFO_768B) -#define F_MAC_IN_FIFO_768B V_MAC_IN_FIFO_768B(1U) - -#define S_T7_1_INT_ERR_INT 29 -#define V_T7_1_INT_ERR_INT(x) ((x) << S_T7_1_INT_ERR_INT) -#define F_T7_1_INT_ERR_INT V_T7_1_INT_ERR_INT(1U) +#define S_T7_INT_ERR_INT 30 +#define V_T7_INT_ERR_INT(x) ((x) << S_T7_INT_ERR_INT) +#define F_T7_INT_ERR_INT V_T7_INT_ERR_INT(1U) #define S_FLOP_PERR 28 #define V_FLOP_PERR(x) ((x) << S_FLOP_PERR) #define F_FLOP_PERR V_FLOP_PERR(1U) -#define S_RPLC_MAP 13 -#define M_RPLC_MAP 0x1fU -#define V_RPLC_MAP(x) ((x) << S_RPLC_MAP) -#define G_RPLC_MAP(x) (((x) >> S_RPLC_MAP) & M_RPLC_MAP) +#define S_MPS_RX_ATRB_MAP_PERR 23 +#define V_MPS_RX_ATRB_MAP_PERR(x) ((x) << S_MPS_RX_ATRB_MAP_PERR) +#define F_MPS_RX_ATRB_MAP_PERR V_MPS_RX_ATRB_MAP_PERR(1U) -#define S_TKN_RUNT_DROP_FIFO 12 -#define V_TKN_RUNT_DROP_FIFO(x) ((x) << S_TKN_RUNT_DROP_FIFO) -#define F_TKN_RUNT_DROP_FIFO V_TKN_RUNT_DROP_FIFO(1U) +#define S_RPLC_MAP_VNI_PERR 18 +#define M_RPLC_MAP_VNI_PERR 0x1fU +#define V_RPLC_MAP_VNI_PERR(x) ((x) << S_RPLC_MAP_VNI_PERR) +#define G_RPLC_MAP_VNI_PERR(x) (((x) >> S_RPLC_MAP_VNI_PERR) & M_RPLC_MAP_VNI_PERR) -#define S_T7_PPM3 9 -#define M_T7_PPM3 0x7U -#define V_T7_PPM3(x) ((x) << S_T7_PPM3) -#define G_T7_PPM3(x) (((x) >> S_T7_PPM3) & M_T7_PPM3) +#define S_RPLC_MAP_MCAST_PERR 13 +#define M_RPLC_MAP_MCAST_PERR 0x1fU +#define V_RPLC_MAP_MCAST_PERR(x) ((x) << S_RPLC_MAP_MCAST_PERR) +#define G_RPLC_MAP_MCAST_PERR(x) (((x) >> S_RPLC_MAP_MCAST_PERR) & M_RPLC_MAP_MCAST_PERR) -#define S_T7_PPM2 6 -#define M_T7_PPM2 0x7U -#define V_T7_PPM2(x) ((x) << S_T7_PPM2) -#define G_T7_PPM2(x) (((x) >> S_T7_PPM2) & M_T7_PPM2) +#define S_PPM3_PERR 9 +#define M_PPM3_PERR 0x7U +#define V_PPM3_PERR(x) ((x) << S_PPM3_PERR) +#define G_PPM3_PERR(x) (((x) >> S_PPM3_PERR) & M_PPM3_PERR) -#define S_T7_PPM1 3 -#define M_T7_PPM1 0x7U -#define V_T7_PPM1(x) ((x) << S_T7_PPM1) -#define G_T7_PPM1(x) (((x) >> S_T7_PPM1) & M_T7_PPM1) +#define S_PPM2_PERR 6 +#define M_PPM2_PERR 0x7U +#define V_PPM2_PERR(x) ((x) << S_PPM2_PERR) +#define G_PPM2_PERR(x) (((x) >> S_PPM2_PERR) & M_PPM2_PERR) -#define S_T7_PPM0 0 -#define M_T7_PPM0 0x7U -#define V_T7_PPM0(x) ((x) << S_T7_PPM0) -#define G_T7_PPM0(x) (((x) >> S_T7_PPM0) & M_T7_PPM0) +#define S_PPM1_PERR 3 +#define M_PPM1_PERR 0x7U +#define V_PPM1_PERR(x) ((x) << S_PPM1_PERR) +#define G_PPM1_PERR(x) (((x) >> S_PPM1_PERR) & M_PPM1_PERR) + +#define S_PPM0_PERR 0 +#define M_PPM0_PERR 0x7U +#define V_PPM0_PERR(x) ((x) << S_PPM0_PERR) +#define G_PPM0_PERR(x) (((x) >> S_PPM0_PERR) & M_PPM0_PERR) #define A_MPS_RX_PERR_INT_ENABLE 0x11078 +#define A_MPS_RX_PERR_ENABLE 0x1107c -#define S_T7_2_INT_ERR_INT 30 -#define V_T7_2_INT_ERR_INT(x) ((x) << S_T7_2_INT_ERR_INT) -#define F_T7_2_INT_ERR_INT V_T7_2_INT_ERR_INT(1U) +#define S_MPS_RX_ATRB_MA_PERRP 23 +#define V_MPS_RX_ATRB_MA_PERRP(x) ((x) << S_MPS_RX_ATRB_MA_PERRP) +#define F_MPS_RX_ATRB_MA_PERRP V_MPS_RX_ATRB_MA_PERRP(1U) + +#define S_RPLC_MAP_VN_PERRI 18 +#define M_RPLC_MAP_VN_PERRI 0x1fU +#define V_RPLC_MAP_VN_PERRI(x) ((x) << S_RPLC_MAP_VN_PERRI) +#define G_RPLC_MAP_VN_PERRI(x) (((x) >> S_RPLC_MAP_VN_PERRI) & M_RPLC_MAP_VN_PERRI) -#define A_MPS_RX_PERR_ENABLE 0x1107c #define A_MPS_RX_PERR_INJECT 0x11080 #define A_MPS_RX_FUNC_INT_CAUSE 0x11084 @@ -43965,6 +44168,38 @@ #define V_LEN_ERR_INT(x) ((x) << S_LEN_ERR_INT) #define F_LEN_ERR_INT V_LEN_ERR_INT(1U) +#define S_MTU_ERR3 19 +#define V_MTU_ERR3(x) ((x) << S_MTU_ERR3) +#define F_MTU_ERR3 V_MTU_ERR3(1U) + +#define S_MTU_ERR2 18 +#define V_MTU_ERR2(x) ((x) << S_MTU_ERR2) +#define F_MTU_ERR2 V_MTU_ERR2(1U) + +#define S_MTU_ERR1 17 +#define V_MTU_ERR1(x) ((x) << S_MTU_ERR1) +#define F_MTU_ERR1 V_MTU_ERR1(1U) + +#define S_MTU_ERR0 16 +#define V_MTU_ERR0(x) ((x) << S_MTU_ERR0) +#define F_MTU_ERR0 V_MTU_ERR0(1U) + +#define S_DBG_LEN_ERR 15 +#define V_DBG_LEN_ERR(x) ((x) << S_DBG_LEN_ERR) +#define F_DBG_LEN_ERR V_DBG_LEN_ERR(1U) + +#define S_DBG_SPI_ERR 14 +#define V_DBG_SPI_ERR(x) ((x) << S_DBG_SPI_ERR) +#define F_DBG_SPI_ERR V_DBG_SPI_ERR(1U) + +#define S_DBG_SE_CNT_ERR 13 +#define V_DBG_SE_CNT_ERR(x) ((x) << S_DBG_SE_CNT_ERR) +#define F_DBG_SE_CNT_ERR V_DBG_SE_CNT_ERR(1U) + +#define S_DBG_SPI_LEN_SE_CNT_ERR 12 +#define V_DBG_SPI_LEN_SE_CNT_ERR(x) ((x) << S_DBG_SPI_LEN_SE_CNT_ERR) +#define F_DBG_SPI_LEN_SE_CNT_ERR V_DBG_SPI_LEN_SE_CNT_ERR(1U) + #define A_MPS_RX_FUNC_INT_ENABLE 0x11088 #define A_MPS_RX_PAUSE_GEN_TH_0 0x1108c @@ -43980,59 +44215,59 @@ #define A_MPS_RX_PERR_INT_CAUSE2 0x1108c -#define S_CRYPT2MPS_RX_INTF_FIFO 28 -#define M_CRYPT2MPS_RX_INTF_FIFO 0xfU -#define V_CRYPT2MPS_RX_INTF_FIFO(x) ((x) << S_CRYPT2MPS_RX_INTF_FIFO) -#define G_CRYPT2MPS_RX_INTF_FIFO(x) (((x) >> S_CRYPT2MPS_RX_INTF_FIFO) & M_CRYPT2MPS_RX_INTF_FIFO) +#define S_CRYPTO2MPS_RX0_PERR 31 +#define V_CRYPTO2MPS_RX0_PERR(x) ((x) << S_CRYPTO2MPS_RX0_PERR) +#define F_CRYPTO2MPS_RX0_PERR V_CRYPTO2MPS_RX0_PERR(1U) -#define S_INIC2MPS_TX0_PERR 27 -#define V_INIC2MPS_TX0_PERR(x) ((x) << S_INIC2MPS_TX0_PERR) -#define F_INIC2MPS_TX0_PERR V_INIC2MPS_TX0_PERR(1U) +#define S_CRYPTO2MPS_RX1_PERR 30 +#define V_CRYPTO2MPS_RX1_PERR(x) ((x) << S_CRYPTO2MPS_RX1_PERR) +#define F_CRYPTO2MPS_RX1_PERR V_CRYPTO2MPS_RX1_PERR(1U) + +#define S_CRYPTO2MPS_RX2_PERR 29 +#define V_CRYPTO2MPS_RX2_PERR(x) ((x) << S_CRYPTO2MPS_RX2_PERR) +#define F_CRYPTO2MPS_RX2_PERR V_CRYPTO2MPS_RX2_PERR(1U) -#define S_INIC2MPS_TX1_PERR 26 +#define S_CRYPTO2MPS_RX3_PERR 28 +#define V_CRYPTO2MPS_RX3_PERR(x) ((x) << S_CRYPTO2MPS_RX3_PERR) +#define F_CRYPTO2MPS_RX3_PERR V_CRYPTO2MPS_RX3_PERR(1U) + +#define S_INIC2MPS_TX1_PERR 27 #define V_INIC2MPS_TX1_PERR(x) ((x) << S_INIC2MPS_TX1_PERR) #define F_INIC2MPS_TX1_PERR V_INIC2MPS_TX1_PERR(1U) -#define S_XGMAC2MPS_RX0_PERR 25 -#define V_XGMAC2MPS_RX0_PERR(x) ((x) << S_XGMAC2MPS_RX0_PERR) -#define F_XGMAC2MPS_RX0_PERR V_XGMAC2MPS_RX0_PERR(1U) +#define S_INIC2MPS_TX0_PERR 26 +#define V_INIC2MPS_TX0_PERR(x) ((x) << S_INIC2MPS_TX0_PERR) +#define F_INIC2MPS_TX0_PERR V_INIC2MPS_TX0_PERR(1U) -#define S_XGMAC2MPS_RX1_PERR 24 +#define S_XGMAC2MPS_RX1_PERR 25 #define V_XGMAC2MPS_RX1_PERR(x) ((x) << S_XGMAC2MPS_RX1_PERR) #define F_XGMAC2MPS_RX1_PERR V_XGMAC2MPS_RX1_PERR(1U) -#define S_MPS2CRYPTO_RX_INTF_FIFO 20 -#define M_MPS2CRYPTO_RX_INTF_FIFO 0xfU -#define V_MPS2CRYPTO_RX_INTF_FIFO(x) ((x) << S_MPS2CRYPTO_RX_INTF_FIFO) -#define G_MPS2CRYPTO_RX_INTF_FIFO(x) (((x) >> S_MPS2CRYPTO_RX_INTF_FIFO) & M_MPS2CRYPTO_RX_INTF_FIFO) - -#define S_MAC_RX_PPROC_MPS2TP_TF 19 -#define V_MAC_RX_PPROC_MPS2TP_TF(x) ((x) << S_MAC_RX_PPROC_MPS2TP_TF) -#define F_MAC_RX_PPROC_MPS2TP_TF V_MAC_RX_PPROC_MPS2TP_TF(1U) - -#define S_MAC_RX_PPROC_LB_CH3 18 -#define V_MAC_RX_PPROC_LB_CH3(x) ((x) << S_MAC_RX_PPROC_LB_CH3) -#define F_MAC_RX_PPROC_LB_CH3 V_MAC_RX_PPROC_LB_CH3(1U) +#define S_XGMAC2MPS_RX0_PERR 24 +#define V_XGMAC2MPS_RX0_PERR(x) ((x) << S_XGMAC2MPS_RX0_PERR) +#define F_XGMAC2MPS_RX0_PERR V_XGMAC2MPS_RX0_PERR(1U) -#define S_MAC_RX_PPROC_LB_CH2 17 -#define V_MAC_RX_PPROC_LB_CH2(x) ((x) << S_MAC_RX_PPROC_LB_CH2) -#define F_MAC_RX_PPROC_LB_CH2 V_MAC_RX_PPROC_LB_CH2(1U) +#define S_MPS2CRYPTO_CH0_INTF_FIFO_PERR 20 +#define M_MPS2CRYPTO_CH0_INTF_FIFO_PERR 0xfU +#define V_MPS2CRYPTO_CH0_INTF_FIFO_PERR(x) ((x) << S_MPS2CRYPTO_CH0_INTF_FIFO_PERR) +#define G_MPS2CRYPTO_CH0_INTF_FIFO_PERR(x) (((x) >> S_MPS2CRYPTO_CH0_INTF_FIFO_PERR) & M_MPS2CRYPTO_CH0_INTF_FIFO_PERR) -#define S_MAC_RX_PPROC_LB_CH1 16 -#define V_MAC_RX_PPROC_LB_CH1(x) ((x) << S_MAC_RX_PPROC_LB_CH1) -#define F_MAC_RX_PPROC_LB_CH1 V_MAC_RX_PPROC_LB_CH1(1U) +#define S_RX_FINAL_TF_FIFO_PERR 19 +#define V_RX_FINAL_TF_FIFO_PERR(x) ((x) << S_RX_FINAL_TF_FIFO_PERR) +#define F_RX_FINAL_TF_FIFO_PERR V_RX_FINAL_TF_FIFO_PERR(1U) -#define S_MAC_RX_PPROC_LB_CH0 15 -#define V_MAC_RX_PPROC_LB_CH0(x) ((x) << S_MAC_RX_PPROC_LB_CH0) -#define F_MAC_RX_PPROC_LB_CH0 V_MAC_RX_PPROC_LB_CH0(1U) +#define S_MPS_LB_FIFO_PERR 15 +#define M_MPS_LB_FIFO_PERR 0xfU +#define V_MPS_LB_FIFO_PERR(x) ((x) << S_MPS_LB_FIFO_PERR) +#define G_MPS_LB_FIFO_PERR(x) (((x) >> S_MPS_LB_FIFO_PERR) & M_MPS_LB_FIFO_PERR) -#define S_MAC_RX_PPROC_DWRR_CH0_3 14 -#define V_MAC_RX_PPROC_DWRR_CH0_3(x) ((x) << S_MAC_RX_PPROC_DWRR_CH0_3) -#define F_MAC_RX_PPROC_DWRR_CH0_3 V_MAC_RX_PPROC_DWRR_CH0_3(1U) +#define S_MPS_DWRR_FIFO_PERR 14 +#define V_MPS_DWRR_FIFO_PERR(x) ((x) << S_MPS_DWRR_FIFO_PERR) +#define F_MPS_DWRR_FIFO_PERR V_MPS_DWRR_FIFO_PERR(1U) -#define S_MAC_RX_FIFO_PERR 13 -#define V_MAC_RX_FIFO_PERR(x) ((x) << S_MAC_RX_FIFO_PERR) -#define F_MAC_RX_FIFO_PERR V_MAC_RX_FIFO_PERR(1U) +#define S_MAC_TF_FIFO_PERR 13 +#define V_MAC_TF_FIFO_PERR(x) ((x) << S_MAC_TF_FIFO_PERR) +#define F_MAC_TF_FIFO_PERR V_MAC_TF_FIFO_PERR(1U) #define S_MAC2MPS_PT3_PERR 12 #define V_MAC2MPS_PT3_PERR(x) ((x) << S_MAC2MPS_PT3_PERR) @@ -44050,13 +44285,18 @@ #define V_MAC2MPS_PT0_PERR(x) ((x) << S_MAC2MPS_PT0_PERR) #define F_MAC2MPS_PT0_PERR V_MAC2MPS_PT0_PERR(1U) -#define S_LPBK_FIFO_PERR 8 -#define V_LPBK_FIFO_PERR(x) ((x) << S_LPBK_FIFO_PERR) -#define F_LPBK_FIFO_PERR V_LPBK_FIFO_PERR(1U) +#define S_TP_LPBK_FIFO_PERR 8 +#define V_TP_LPBK_FIFO_PERR(x) ((x) << S_TP_LPBK_FIFO_PERR) +#define F_TP_LPBK_FIFO_PERR V_TP_LPBK_FIFO_PERR(1U) -#define S_TP2MPS_TF_FIFO_PERR 7 -#define V_TP2MPS_TF_FIFO_PERR(x) ((x) << S_TP2MPS_TF_FIFO_PERR) -#define F_TP2MPS_TF_FIFO_PERR V_TP2MPS_TF_FIFO_PERR(1U) +#define S_TP_LPBK_TF_PERR 7 +#define V_TP_LPBK_TF_PERR(x) ((x) << S_TP_LPBK_TF_PERR) +#define F_TP_LPBK_TF_PERR V_TP_LPBK_TF_PERR(1U) + +#define S_RSDV1 0 +#define M_RSDV1 0x7fU +#define V_RSDV1(x) ((x) << S_RSDV1) +#define G_RSDV1(x) (((x) >> S_RSDV1) & M_RSDV1) #define A_MPS_RX_PAUSE_GEN_TH_1 0x11090 #define A_MPS_RX_PERR_INT_ENABLE2 0x11090 @@ -44978,67 +45218,407 @@ #define A_MPS_VF_RPLCT_MAP6 0x11308 #define A_MPS_VF_RPLCT_MAP7 0x1130c #define A_MPS_RX_PERR_INT_CAUSE3 0x11310 + +#define S_FIFO_REPL_CH3_CERR 28 +#define V_FIFO_REPL_CH3_CERR(x) ((x) << S_FIFO_REPL_CH3_CERR) +#define F_FIFO_REPL_CH3_CERR V_FIFO_REPL_CH3_CERR(1U) + +#define S_FIFO_REPL_CH2_CERR 27 +#define V_FIFO_REPL_CH2_CERR(x) ((x) << S_FIFO_REPL_CH2_CERR) +#define F_FIFO_REPL_CH2_CERR V_FIFO_REPL_CH2_CERR(1U) + +#define S_FIFO_REPL_CH1_CERR 26 +#define V_FIFO_REPL_CH1_CERR(x) ((x) << S_FIFO_REPL_CH1_CERR) +#define F_FIFO_REPL_CH1_CERR V_FIFO_REPL_CH1_CERR(1U) + +#define S_FIFO_REPL_CH0_CERR 25 +#define V_FIFO_REPL_CH0_CERR(x) ((x) << S_FIFO_REPL_CH0_CERR) +#define F_FIFO_REPL_CH0_CERR V_FIFO_REPL_CH0_CERR(1U) + +#define S_VLAN_FILTER_RAM_CERR 24 +#define V_VLAN_FILTER_RAM_CERR(x) ((x) << S_VLAN_FILTER_RAM_CERR) +#define F_VLAN_FILTER_RAM_CERR V_VLAN_FILTER_RAM_CERR(1U) + +#define S_MPS_RX_TD_STAT_FIFO_PERR_CH3 23 +#define V_MPS_RX_TD_STAT_FIFO_PERR_CH3(x) ((x) << S_MPS_RX_TD_STAT_FIFO_PERR_CH3) +#define F_MPS_RX_TD_STAT_FIFO_PERR_CH3 V_MPS_RX_TD_STAT_FIFO_PERR_CH3(1U) + +#define S_RPLCT_HDR_FIFO_IN_PERR_CH3 22 +#define V_RPLCT_HDR_FIFO_IN_PERR_CH3(x) ((x) << S_RPLCT_HDR_FIFO_IN_PERR_CH3) +#define F_RPLCT_HDR_FIFO_IN_PERR_CH3 V_RPLCT_HDR_FIFO_IN_PERR_CH3(1U) + +#define S_ID_FIFO_IN_PERR_CH3 21 +#define V_ID_FIFO_IN_PERR_CH3(x) ((x) << S_ID_FIFO_IN_PERR_CH3) +#define F_ID_FIFO_IN_PERR_CH3 V_ID_FIFO_IN_PERR_CH3(1U) + +#define S_DESC_HDR2_PERR_CH3 20 +#define V_DESC_HDR2_PERR_CH3(x) ((x) << S_DESC_HDR2_PERR_CH3) +#define F_DESC_HDR2_PERR_CH3 V_DESC_HDR2_PERR_CH3(1U) + +#define S_FIFO_REPL_PERR_CH3 19 +#define V_FIFO_REPL_PERR_CH3(x) ((x) << S_FIFO_REPL_PERR_CH3) +#define F_FIFO_REPL_PERR_CH3 V_FIFO_REPL_PERR_CH3(1U) + +#define S_MPS_RX_TD_PERR_CH3 18 +#define V_MPS_RX_TD_PERR_CH3(x) ((x) << S_MPS_RX_TD_PERR_CH3) +#define F_MPS_RX_TD_PERR_CH3 V_MPS_RX_TD_PERR_CH3(1U) + +#define S_MPS_RX_TD_STAT_FIFO_PERR_CH2 17 +#define V_MPS_RX_TD_STAT_FIFO_PERR_CH2(x) ((x) << S_MPS_RX_TD_STAT_FIFO_PERR_CH2) +#define F_MPS_RX_TD_STAT_FIFO_PERR_CH2 V_MPS_RX_TD_STAT_FIFO_PERR_CH2(1U) + +#define S_RPLCT_HDR_FIFO_IN_PERR_CH2 16 +#define V_RPLCT_HDR_FIFO_IN_PERR_CH2(x) ((x) << S_RPLCT_HDR_FIFO_IN_PERR_CH2) +#define F_RPLCT_HDR_FIFO_IN_PERR_CH2 V_RPLCT_HDR_FIFO_IN_PERR_CH2(1U) + +#define S_ID_FIFO_IN_PERR_CH2 15 +#define V_ID_FIFO_IN_PERR_CH2(x) ((x) << S_ID_FIFO_IN_PERR_CH2) +#define F_ID_FIFO_IN_PERR_CH2 V_ID_FIFO_IN_PERR_CH2(1U) + +#define S_DESC_HDR2_PERR_CH2 14 +#define V_DESC_HDR2_PERR_CH2(x) ((x) << S_DESC_HDR2_PERR_CH2) +#define F_DESC_HDR2_PERR_CH2 V_DESC_HDR2_PERR_CH2(1U) + +#define S_FIFO_REPL_PERR_CH2 13 +#define V_FIFO_REPL_PERR_CH2(x) ((x) << S_FIFO_REPL_PERR_CH2) +#define F_FIFO_REPL_PERR_CH2 V_FIFO_REPL_PERR_CH2(1U) + +#define S_MPS_RX_TD_PERR_CH2 12 +#define V_MPS_RX_TD_PERR_CH2(x) ((x) << S_MPS_RX_TD_PERR_CH2) +#define F_MPS_RX_TD_PERR_CH2 V_MPS_RX_TD_PERR_CH2(1U) + +#define S_MPS_RX_TD_STAT_FIFO_PERR_CH1 11 +#define V_MPS_RX_TD_STAT_FIFO_PERR_CH1(x) ((x) << S_MPS_RX_TD_STAT_FIFO_PERR_CH1) +#define F_MPS_RX_TD_STAT_FIFO_PERR_CH1 V_MPS_RX_TD_STAT_FIFO_PERR_CH1(1U) + +#define S_RPLCT_HDR_FIFO_IN_PERR_CH1 10 +#define V_RPLCT_HDR_FIFO_IN_PERR_CH1(x) ((x) << S_RPLCT_HDR_FIFO_IN_PERR_CH1) +#define F_RPLCT_HDR_FIFO_IN_PERR_CH1 V_RPLCT_HDR_FIFO_IN_PERR_CH1(1U) + +#define S_ID_FIFO_IN_PERR_CH1 9 +#define V_ID_FIFO_IN_PERR_CH1(x) ((x) << S_ID_FIFO_IN_PERR_CH1) +#define F_ID_FIFO_IN_PERR_CH1 V_ID_FIFO_IN_PERR_CH1(1U) + +#define S_DESC_HDR2_PERR_CH1 8 +#define V_DESC_HDR2_PERR_CH1(x) ((x) << S_DESC_HDR2_PERR_CH1) +#define F_DESC_HDR2_PERR_CH1 V_DESC_HDR2_PERR_CH1(1U) + +#define S_FIFO_REPL_PERR_CH1 7 +#define V_FIFO_REPL_PERR_CH1(x) ((x) << S_FIFO_REPL_PERR_CH1) +#define F_FIFO_REPL_PERR_CH1 V_FIFO_REPL_PERR_CH1(1U) + +#define S_MPS_RX_TD_PERR_CH1 6 +#define V_MPS_RX_TD_PERR_CH1(x) ((x) << S_MPS_RX_TD_PERR_CH1) +#define F_MPS_RX_TD_PERR_CH1 V_MPS_RX_TD_PERR_CH1(1U) + +#define S_MPS_RX_TD_STAT_FIFO_PERR_CH0 5 +#define V_MPS_RX_TD_STAT_FIFO_PERR_CH0(x) ((x) << S_MPS_RX_TD_STAT_FIFO_PERR_CH0) +#define F_MPS_RX_TD_STAT_FIFO_PERR_CH0 V_MPS_RX_TD_STAT_FIFO_PERR_CH0(1U) + +#define S_RPLCT_HDR_FIFO_IN_PERR_CH0 4 +#define V_RPLCT_HDR_FIFO_IN_PERR_CH0(x) ((x) << S_RPLCT_HDR_FIFO_IN_PERR_CH0) +#define F_RPLCT_HDR_FIFO_IN_PERR_CH0 V_RPLCT_HDR_FIFO_IN_PERR_CH0(1U) + +#define S_ID_FIFO_IN_PERR_CH0 3 +#define V_ID_FIFO_IN_PERR_CH0(x) ((x) << S_ID_FIFO_IN_PERR_CH0) +#define F_ID_FIFO_IN_PERR_CH0 V_ID_FIFO_IN_PERR_CH0(1U) + +#define S_DESC_HDR2_PERR_CH0 2 +#define V_DESC_HDR2_PERR_CH0(x) ((x) << S_DESC_HDR2_PERR_CH0) +#define F_DESC_HDR2_PERR_CH0 V_DESC_HDR2_PERR_CH0(1U) + +#define S_FIFO_REPL_PERR_CH0 1 +#define V_FIFO_REPL_PERR_CH0(x) ((x) << S_FIFO_REPL_PERR_CH0) +#define F_FIFO_REPL_PERR_CH0 V_FIFO_REPL_PERR_CH0(1U) + +#define S_MPS_RX_TD_PERR_CH0 0 +#define V_MPS_RX_TD_PERR_CH0(x) ((x) << S_MPS_RX_TD_PERR_CH0) +#define F_MPS_RX_TD_PERR_CH0 V_MPS_RX_TD_PERR_CH0(1U) + #define A_MPS_RX_PERR_INT_ENABLE3 0x11314 #define A_MPS_RX_PERR_ENABLE3 0x11318 #define A_MPS_RX_PERR_INT_CAUSE4 0x1131c -#define S_CLS 20 -#define M_CLS 0x3fU -#define V_CLS(x) ((x) << S_CLS) -#define G_CLS(x) (((x) >> S_CLS) & M_CLS) +#define S_VNI_MULTICAST_FIFO_ECC_ERR_CH3 30 +#define V_VNI_MULTICAST_FIFO_ECC_ERR_CH3(x) ((x) << S_VNI_MULTICAST_FIFO_ECC_ERR_CH3) +#define F_VNI_MULTICAST_FIFO_ECC_ERR_CH3 V_VNI_MULTICAST_FIFO_ECC_ERR_CH3(1U) + +#define S_VNI_MULTICAST_FIFO_ECC_ERR_CH2 29 +#define V_VNI_MULTICAST_FIFO_ECC_ERR_CH2(x) ((x) << S_VNI_MULTICAST_FIFO_ECC_ERR_CH2) +#define F_VNI_MULTICAST_FIFO_ECC_ERR_CH2 V_VNI_MULTICAST_FIFO_ECC_ERR_CH2(1U) + +#define S_HASH_SRAM_CLS_ENG1 28 +#define V_HASH_SRAM_CLS_ENG1(x) ((x) << S_HASH_SRAM_CLS_ENG1) +#define F_HASH_SRAM_CLS_ENG1 V_HASH_SRAM_CLS_ENG1(1U) + +#define S_HASH_SRAM_CLS_ENG0 27 +#define V_HASH_SRAM_CLS_ENG0(x) ((x) << S_HASH_SRAM_CLS_ENG0) +#define F_HASH_SRAM_CLS_ENG0 V_HASH_SRAM_CLS_ENG0(1U) + +#define S_CLS_TCAM_SRAM_CLS_ENG1 26 +#define V_CLS_TCAM_SRAM_CLS_ENG1(x) ((x) << S_CLS_TCAM_SRAM_CLS_ENG1) +#define F_CLS_TCAM_SRAM_CLS_ENG1 V_CLS_TCAM_SRAM_CLS_ENG1(1U) + +#define S_CLS_TCAM_CRC_SRAM_CLS_ENG1 25 +#define V_CLS_TCAM_CRC_SRAM_CLS_ENG1(x) ((x) << S_CLS_TCAM_CRC_SRAM_CLS_ENG1) +#define F_CLS_TCAM_CRC_SRAM_CLS_ENG1 V_CLS_TCAM_CRC_SRAM_CLS_ENG1(1U) + +#define S_CLS_TCAM_SRAM_CLS_ENG0 24 +#define V_CLS_TCAM_SRAM_CLS_ENG0(x) ((x) << S_CLS_TCAM_SRAM_CLS_ENG0) +#define F_CLS_TCAM_SRAM_CLS_ENG0 V_CLS_TCAM_SRAM_CLS_ENG0(1U) + +#define S_CLS_TCAM_CRC_SRAM_CLS_ENG0 23 +#define V_CLS_TCAM_CRC_SRAM_CLS_ENG0(x) ((x) << S_CLS_TCAM_CRC_SRAM_CLS_ENG0) +#define F_CLS_TCAM_CRC_SRAM_CLS_ENG0 V_CLS_TCAM_CRC_SRAM_CLS_ENG0(1U) + +#define S_LB_FIFO_ECC_ERR 19 +#define M_LB_FIFO_ECC_ERR 0xfU +#define V_LB_FIFO_ECC_ERR(x) ((x) << S_LB_FIFO_ECC_ERR) +#define G_LB_FIFO_ECC_ERR(x) (((x) >> S_LB_FIFO_ECC_ERR) & M_LB_FIFO_ECC_ERR) + +#define S_DWRR_CH_FIFO_ECC_ERR 18 +#define V_DWRR_CH_FIFO_ECC_ERR(x) ((x) << S_DWRR_CH_FIFO_ECC_ERR) +#define F_DWRR_CH_FIFO_ECC_ERR V_DWRR_CH_FIFO_ECC_ERR(1U) + +#define S_MAC_RX_FIFO_ECC_ERR 17 +#define V_MAC_RX_FIFO_ECC_ERR(x) ((x) << S_MAC_RX_FIFO_ECC_ERR) +#define F_MAC_RX_FIFO_ECC_ERR V_MAC_RX_FIFO_ECC_ERR(1U) + +#define S_LPBK_RX_FIFO_ECC_ERR 16 +#define V_LPBK_RX_FIFO_ECC_ERR(x) ((x) << S_LPBK_RX_FIFO_ECC_ERR) +#define F_LPBK_RX_FIFO_ECC_ERR V_LPBK_RX_FIFO_ECC_ERR(1U) + +#define S_CRS_DATA_STORE_N_FWD_CH3 15 +#define V_CRS_DATA_STORE_N_FWD_CH3(x) ((x) << S_CRS_DATA_STORE_N_FWD_CH3) +#define F_CRS_DATA_STORE_N_FWD_CH3 V_CRS_DATA_STORE_N_FWD_CH3(1U) + +#define S_TRACE_FWD_FIFO_CERR_CH3 14 +#define V_TRACE_FWD_FIFO_CERR_CH3(x) ((x) << S_TRACE_FWD_FIFO_CERR_CH3) +#define F_TRACE_FWD_FIFO_CERR_CH3 V_TRACE_FWD_FIFO_CERR_CH3(1U) -#define S_RX_PRE_PROC 16 -#define M_RX_PRE_PROC 0xfU -#define V_RX_PRE_PROC(x) ((x) << S_RX_PRE_PROC) -#define G_RX_PRE_PROC(x) (((x) >> S_RX_PRE_PROC) & M_RX_PRE_PROC) +#define S_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH3 13 +#define V_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH3(x) ((x) << S_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH3) +#define F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH3 V_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH3(1U) -#define S_PPROC3 12 -#define M_PPROC3 0xfU -#define V_PPROC3(x) ((x) << S_PPROC3) -#define G_PPROC3(x) (((x) >> S_PPROC3) & M_PPROC3) +#define S_PTP_TRACE_FWD_FIFO_CERR_CH3 12 +#define V_PTP_TRACE_FWD_FIFO_CERR_CH3(x) ((x) << S_PTP_TRACE_FWD_FIFO_CERR_CH3) +#define F_PTP_TRACE_FWD_FIFO_CERR_CH3 V_PTP_TRACE_FWD_FIFO_CERR_CH3(1U) -#define S_PPROC2 8 -#define M_PPROC2 0xfU -#define V_PPROC2(x) ((x) << S_PPROC2) -#define G_PPROC2(x) (((x) >> S_PPROC2) & M_PPROC2) +#define S_CRS_DATA_STORE_N_FWD_CH2 11 +#define V_CRS_DATA_STORE_N_FWD_CH2(x) ((x) << S_CRS_DATA_STORE_N_FWD_CH2) +#define F_CRS_DATA_STORE_N_FWD_CH2 V_CRS_DATA_STORE_N_FWD_CH2(1U) -#define S_PPROC1 4 -#define M_PPROC1 0xfU -#define V_PPROC1(x) ((x) << S_PPROC1) -#define G_PPROC1(x) (((x) >> S_PPROC1) & M_PPROC1) +#define S_TRACE_FWD_FIFO_CERR_CH2 10 +#define V_TRACE_FWD_FIFO_CERR_CH2(x) ((x) << S_TRACE_FWD_FIFO_CERR_CH2) +#define F_TRACE_FWD_FIFO_CERR_CH2 V_TRACE_FWD_FIFO_CERR_CH2(1U) -#define S_PPROC0 0 -#define M_PPROC0 0xfU -#define V_PPROC0(x) ((x) << S_PPROC0) -#define G_PPROC0(x) (((x) >> S_PPROC0) & M_PPROC0) +#define S_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH2 9 +#define V_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH2(x) ((x) << S_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH2) +#define F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH2 V_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH2(1U) + +#define S_PTP_TRACE_FWD_FIFO_CERR_CH2 8 +#define V_PTP_TRACE_FWD_FIFO_CERR_CH2(x) ((x) << S_PTP_TRACE_FWD_FIFO_CERR_CH2) +#define F_PTP_TRACE_FWD_FIFO_CERR_CH2 V_PTP_TRACE_FWD_FIFO_CERR_CH2(1U) + +#define S_CRS_DATA_STORE_N_FWD_CH1 7 +#define V_CRS_DATA_STORE_N_FWD_CH1(x) ((x) << S_CRS_DATA_STORE_N_FWD_CH1) +#define F_CRS_DATA_STORE_N_FWD_CH1 V_CRS_DATA_STORE_N_FWD_CH1(1U) + +#define S_TRACE_FWD_FIFO_CERR_CH1 6 +#define V_TRACE_FWD_FIFO_CERR_CH1(x) ((x) << S_TRACE_FWD_FIFO_CERR_CH1) +#define F_TRACE_FWD_FIFO_CERR_CH1 V_TRACE_FWD_FIFO_CERR_CH1(1U) + +#define S_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH1 5 +#define V_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH1(x) ((x) << S_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH1) +#define F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH1 V_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH1(1U) + +#define S_PTP_TRACE_FWD_FIFO_CERR_CH1 4 +#define V_PTP_TRACE_FWD_FIFO_CERR_CH1(x) ((x) << S_PTP_TRACE_FWD_FIFO_CERR_CH1) +#define F_PTP_TRACE_FWD_FIFO_CERR_CH1 V_PTP_TRACE_FWD_FIFO_CERR_CH1(1U) + +#define S_CRS_DATA_STORE_N_FWD_CH0 3 +#define V_CRS_DATA_STORE_N_FWD_CH0(x) ((x) << S_CRS_DATA_STORE_N_FWD_CH0) +#define F_CRS_DATA_STORE_N_FWD_CH0 V_CRS_DATA_STORE_N_FWD_CH0(1U) + +#define S_TRACE_FWD_FIFO_CERR_CH0 2 +#define V_TRACE_FWD_FIFO_CERR_CH0(x) ((x) << S_TRACE_FWD_FIFO_CERR_CH0) +#define F_TRACE_FWD_FIFO_CERR_CH0 V_TRACE_FWD_FIFO_CERR_CH0(1U) + +#define S_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH0 1 +#define V_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH0(x) ((x) << S_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH0) +#define F_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH0 V_TRANSPARENT_ENCAP_FWD_FIFO_CERR_CH0(1U) + +#define S_PTP_TRACE_FWD_FIFO_CERR_CH0 0 +#define V_PTP_TRACE_FWD_FIFO_CERR_CH0(x) ((x) << S_PTP_TRACE_FWD_FIFO_CERR_CH0) +#define F_PTP_TRACE_FWD_FIFO_CERR_CH0 V_PTP_TRACE_FWD_FIFO_CERR_CH0(1U) #define A_MPS_RX_PERR_INT_ENABLE4 0x11320 #define A_MPS_RX_PERR_ENABLE4 0x11324 #define A_MPS_RX_PERR_INT_CAUSE5 0x11328 -#define S_MPS2CRYP_RX_FIFO 26 -#define M_MPS2CRYP_RX_FIFO 0xfU -#define V_MPS2CRYP_RX_FIFO(x) ((x) << S_MPS2CRYP_RX_FIFO) -#define G_MPS2CRYP_RX_FIFO(x) (((x) >> S_MPS2CRYP_RX_FIFO) & M_MPS2CRYP_RX_FIFO) +#define S_MPS2CRYP_RX_FIFO3_PERR 31 +#define V_MPS2CRYP_RX_FIFO3_PERR(x) ((x) << S_MPS2CRYP_RX_FIFO3_PERR) +#define F_MPS2CRYP_RX_FIFO3_PERR V_MPS2CRYP_RX_FIFO3_PERR(1U) + +#define S_MPS2CRYP_RX_FIFO2_PERR 30 +#define V_MPS2CRYP_RX_FIFO2_PERR(x) ((x) << S_MPS2CRYP_RX_FIFO2_PERR) +#define F_MPS2CRYP_RX_FIFO2_PERR V_MPS2CRYP_RX_FIFO2_PERR(1U) + +#define S_MPS2CRYP_RX_FIFO1_PERR 29 +#define V_MPS2CRYP_RX_FIFO1_PERR(x) ((x) << S_MPS2CRYP_RX_FIFO1_PERR) +#define F_MPS2CRYP_RX_FIFO1_PERR V_MPS2CRYP_RX_FIFO1_PERR(1U) + +#define S_MPS2CRYP_RX_FIFO0_PERR 28 +#define V_MPS2CRYP_RX_FIFO0_PERR(x) ((x) << S_MPS2CRYP_RX_FIFO0_PERR) +#define F_MPS2CRYP_RX_FIFO0_PERR V_MPS2CRYP_RX_FIFO0_PERR(1U) + +#define S_VNI_MULTICAST_SRAM2_PERR 27 +#define V_VNI_MULTICAST_SRAM2_PERR(x) ((x) << S_VNI_MULTICAST_SRAM2_PERR) +#define F_VNI_MULTICAST_SRAM2_PERR V_VNI_MULTICAST_SRAM2_PERR(1U) + +#define S_VNI_MULTICAST_SRAM1_PERR 26 +#define V_VNI_MULTICAST_SRAM1_PERR(x) ((x) << S_VNI_MULTICAST_SRAM1_PERR) +#define F_VNI_MULTICAST_SRAM1_PERR V_VNI_MULTICAST_SRAM1_PERR(1U) + +#define S_VNI_MULTICAST_SRAM0_PERR 25 +#define V_VNI_MULTICAST_SRAM0_PERR(x) ((x) << S_VNI_MULTICAST_SRAM0_PERR) +#define F_VNI_MULTICAST_SRAM0_PERR V_VNI_MULTICAST_SRAM0_PERR(1U) + +#define S_MAC_MULTICAST_SRAM4_PERR 24 +#define V_MAC_MULTICAST_SRAM4_PERR(x) ((x) << S_MAC_MULTICAST_SRAM4_PERR) +#define F_MAC_MULTICAST_SRAM4_PERR V_MAC_MULTICAST_SRAM4_PERR(1U) + +#define S_MAC_MULTICAST_SRAM3_PERR 23 +#define V_MAC_MULTICAST_SRAM3_PERR(x) ((x) << S_MAC_MULTICAST_SRAM3_PERR) +#define F_MAC_MULTICAST_SRAM3_PERR V_MAC_MULTICAST_SRAM3_PERR(1U) + +#define S_MAC_MULTICAST_SRAM2_PERR 22 +#define V_MAC_MULTICAST_SRAM2_PERR(x) ((x) << S_MAC_MULTICAST_SRAM2_PERR) +#define F_MAC_MULTICAST_SRAM2_PERR V_MAC_MULTICAST_SRAM2_PERR(1U) + +#define S_MAC_MULTICAST_SRAM1_PERR 21 +#define V_MAC_MULTICAST_SRAM1_PERR(x) ((x) << S_MAC_MULTICAST_SRAM1_PERR) +#define F_MAC_MULTICAST_SRAM1_PERR V_MAC_MULTICAST_SRAM1_PERR(1U) + +#define S_MAC_MULTICAST_SRAM0_PERR 20 +#define V_MAC_MULTICAST_SRAM0_PERR(x) ((x) << S_MAC_MULTICAST_SRAM0_PERR) +#define F_MAC_MULTICAST_SRAM0_PERR V_MAC_MULTICAST_SRAM0_PERR(1U) + +#define S_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR 19 +#define V_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR(x) ((x) << S_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR) +#define F_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR V_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR(1U) + +#define S_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR 18 +#define V_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR(x) ((x) << S_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR) +#define F_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR V_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR(1U) + +#define S_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR 17 +#define V_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR(x) ((x) << S_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR) +#define F_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR V_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR(1U) + +#define S_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR 16 +#define V_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR(x) ((x) << S_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR) +#define F_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR V_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR(1U) + +#define S_MEM_WRAP_CR2MPS_RX_FIFO3_PERR 15 +#define V_MEM_WRAP_CR2MPS_RX_FIFO3_PERR(x) ((x) << S_MEM_WRAP_CR2MPS_RX_FIFO3_PERR) +#define F_MEM_WRAP_CR2MPS_RX_FIFO3_PERR V_MEM_WRAP_CR2MPS_RX_FIFO3_PERR(1U) + +#define S_MEM_WRAP_CR2MPS_RX_FIFO2_PERR 14 +#define V_MEM_WRAP_CR2MPS_RX_FIFO2_PERR(x) ((x) << S_MEM_WRAP_CR2MPS_RX_FIFO2_PERR) +#define F_MEM_WRAP_CR2MPS_RX_FIFO2_PERR V_MEM_WRAP_CR2MPS_RX_FIFO2_PERR(1U) + +#define S_MEM_WRAP_CR2MPS_RX_FIFO1_PERR 13 +#define V_MEM_WRAP_CR2MPS_RX_FIFO1_PERR(x) ((x) << S_MEM_WRAP_CR2MPS_RX_FIFO1_PERR) +#define F_MEM_WRAP_CR2MPS_RX_FIFO1_PERR V_MEM_WRAP_CR2MPS_RX_FIFO1_PERR(1U) + +#define S_MEM_WRAP_CR2MPS_RX_FIFO0_PERR 12 +#define V_MEM_WRAP_CR2MPS_RX_FIFO0_PERR(x) ((x) << S_MEM_WRAP_CR2MPS_RX_FIFO0_PERR) +#define F_MEM_WRAP_CR2MPS_RX_FIFO0_PERR V_MEM_WRAP_CR2MPS_RX_FIFO0_PERR(1U) -#define S_RX_OUT 20 -#define M_RX_OUT 0x3fU -#define V_RX_OUT(x) ((x) << S_RX_OUT) -#define G_RX_OUT(x) (((x) >> S_RX_OUT) & M_RX_OUT) +#define S_MEM_WRAP_NON_IPSEC_FIFO3_PERR 11 +#define V_MEM_WRAP_NON_IPSEC_FIFO3_PERR(x) ((x) << S_MEM_WRAP_NON_IPSEC_FIFO3_PERR) +#define F_MEM_WRAP_NON_IPSEC_FIFO3_PERR V_MEM_WRAP_NON_IPSEC_FIFO3_PERR(1U) -#define S_MEM_WRAP 0 -#define M_MEM_WRAP 0xfffffU -#define V_MEM_WRAP(x) ((x) << S_MEM_WRAP) -#define G_MEM_WRAP(x) (((x) >> S_MEM_WRAP) & M_MEM_WRAP) +#define S_MEM_WRAP_NON_IPSEC_FIFO2_PERR 10 +#define V_MEM_WRAP_NON_IPSEC_FIFO2_PERR(x) ((x) << S_MEM_WRAP_NON_IPSEC_FIFO2_PERR) +#define F_MEM_WRAP_NON_IPSEC_FIFO2_PERR V_MEM_WRAP_NON_IPSEC_FIFO2_PERR(1U) + +#define S_MEM_WRAP_NON_IPSEC_FIFO1_PERR 9 +#define V_MEM_WRAP_NON_IPSEC_FIFO1_PERR(x) ((x) << S_MEM_WRAP_NON_IPSEC_FIFO1_PERR) +#define F_MEM_WRAP_NON_IPSEC_FIFO1_PERR V_MEM_WRAP_NON_IPSEC_FIFO1_PERR(1U) + +#define S_MEM_WRAP_NON_IPSEC_FIFO0_PERR 8 +#define V_MEM_WRAP_NON_IPSEC_FIFO0_PERR(x) ((x) << S_MEM_WRAP_NON_IPSEC_FIFO0_PERR) +#define F_MEM_WRAP_NON_IPSEC_FIFO0_PERR V_MEM_WRAP_NON_IPSEC_FIFO0_PERR(1U) + +#define S_MEM_WRAP_TP_DB_REQ_FIFO3_PERR 7 +#define V_MEM_WRAP_TP_DB_REQ_FIFO3_PERR(x) ((x) << S_MEM_WRAP_TP_DB_REQ_FIFO3_PERR) +#define F_MEM_WRAP_TP_DB_REQ_FIFO3_PERR V_MEM_WRAP_TP_DB_REQ_FIFO3_PERR(1U) + +#define S_MEM_WRAP_TP_DB_REQ_FIFO2_PERR 6 +#define V_MEM_WRAP_TP_DB_REQ_FIFO2_PERR(x) ((x) << S_MEM_WRAP_TP_DB_REQ_FIFO2_PERR) +#define F_MEM_WRAP_TP_DB_REQ_FIFO2_PERR V_MEM_WRAP_TP_DB_REQ_FIFO2_PERR(1U) + +#define S_MEM_WRAP_TP_DB_REQ_FIFO1_PERR 5 +#define V_MEM_WRAP_TP_DB_REQ_FIFO1_PERR(x) ((x) << S_MEM_WRAP_TP_DB_REQ_FIFO1_PERR) +#define F_MEM_WRAP_TP_DB_REQ_FIFO1_PERR V_MEM_WRAP_TP_DB_REQ_FIFO1_PERR(1U) + +#define S_MEM_WRAP_TP_DB_REQ_FIFO0_PERR 4 +#define V_MEM_WRAP_TP_DB_REQ_FIFO0_PERR(x) ((x) << S_MEM_WRAP_TP_DB_REQ_FIFO0_PERR) +#define F_MEM_WRAP_TP_DB_REQ_FIFO0_PERR V_MEM_WRAP_TP_DB_REQ_FIFO0_PERR(1U) + +#define S_MEM_WRAP_CNTRL_FIFO3_PERR 3 +#define V_MEM_WRAP_CNTRL_FIFO3_PERR(x) ((x) << S_MEM_WRAP_CNTRL_FIFO3_PERR) +#define F_MEM_WRAP_CNTRL_FIFO3_PERR V_MEM_WRAP_CNTRL_FIFO3_PERR(1U) + +#define S_MEM_WRAP_CNTRL_FIFO2_PERR 2 +#define V_MEM_WRAP_CNTRL_FIFO2_PERR(x) ((x) << S_MEM_WRAP_CNTRL_FIFO2_PERR) +#define F_MEM_WRAP_CNTRL_FIFO2_PERR V_MEM_WRAP_CNTRL_FIFO2_PERR(1U) + +#define S_MEM_WRAP_CNTRL_FIFO1_PERR 1 +#define V_MEM_WRAP_CNTRL_FIFO1_PERR(x) ((x) << S_MEM_WRAP_CNTRL_FIFO1_PERR) +#define F_MEM_WRAP_CNTRL_FIFO1_PERR V_MEM_WRAP_CNTRL_FIFO1_PERR(1U) + +#define S_MEM_WRAP_CNTRL_FIFO0_PERR 0 +#define V_MEM_WRAP_CNTRL_FIFO0_PERR(x) ((x) << S_MEM_WRAP_CNTRL_FIFO0_PERR) +#define F_MEM_WRAP_CNTRL_FIFO0_PERR V_MEM_WRAP_CNTRL_FIFO0_PERR(1U) #define A_MPS_RX_PERR_INT_ENABLE5 0x1132c #define A_MPS_RX_PERR_ENABLE5 0x11330 #define A_MPS_RX_PERR_INT_CAUSE6 0x11334 -#define S_MPS_RX_MEM_WRAP 0 -#define M_MPS_RX_MEM_WRAP 0x1ffffffU -#define V_MPS_RX_MEM_WRAP(x) ((x) << S_MPS_RX_MEM_WRAP) -#define G_MPS_RX_MEM_WRAP(x) (((x) >> S_MPS_RX_MEM_WRAP) & M_MPS_RX_MEM_WRAP) +#define S_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR 23 +#define V_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR(x) ((x) << S_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR) +#define F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR V_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO3_PERR(1U) + +#define S_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR 22 +#define V_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR(x) ((x) << S_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR) +#define F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR V_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO2_PERR(1U) + +#define S_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR 21 +#define V_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR(x) ((x) << S_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR) +#define F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR V_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO1_PERR(1U) + +#define S_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR 20 +#define V_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR(x) ((x) << S_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR) +#define F_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR V_T7_MEM_WRAP_IPSEC_HDR_UPD_FIFO0_PERR(1U) + +#define S_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO3_PERR 19 +#define V_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO3_PERR(x) ((x) << S_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO3_PERR) +#define F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO3_PERR V_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO3_PERR(1U) + +#define S_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO2_PERR 18 +#define V_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO2_PERR(x) ((x) << S_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO2_PERR) +#define F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO2_PERR V_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO2_PERR(1U) + +#define S_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO1_PERR 17 +#define V_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO1_PERR(x) ((x) << S_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO1_PERR) +#define F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO1_PERR V_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO1_PERR(1U) + +#define S_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO0_PERR 16 +#define V_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO0_PERR(x) ((x) << S_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO0_PERR) +#define F_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO0_PERR V_MEM_WRAP_CR2MPS_UPDTD_HDR_FIFO0_PERR(1U) #define A_MPS_RX_PERR_INT_ENABLE6 0x11338 #define A_MPS_RX_PERR_ENABLE6 0x1133c @@ -45844,6 +46424,18 @@ #define V_SLVFIFO(x) ((x) << S_SLVFIFO) #define F_SLVFIFO V_SLVFIFO(1U) +#define S_T7_MSTTXFIFO 22 +#define V_T7_MSTTXFIFO(x) ((x) << S_T7_MSTTXFIFO) +#define F_T7_MSTTXFIFO V_T7_MSTTXFIFO(1U) + +#define S_T7_MSTRXFIFO 21 +#define V_T7_MSTRXFIFO(x) ((x) << S_T7_MSTRXFIFO) +#define F_T7_MSTRXFIFO V_T7_MSTRXFIFO(1U) + +#define S_T7_SLVFIFO 20 +#define V_T7_SLVFIFO(x) ((x) << S_T7_SLVFIFO) +#define F_T7_SLVFIFO V_T7_SLVFIFO(1U) + #define A_SMB_PERR_INJ 0x1909c #define S_MSTTXINJDATAERR 3 @@ -46167,20 +46759,20 @@ #define V_UART_CLKDIV(x) ((x) << S_UART_CLKDIV) #define G_UART_CLKDIV(x) (((x) >> S_UART_CLKDIV) & M_UART_CLKDIV) -#define S_T7_STOPBITS 25 -#define M_T7_STOPBITS 0x3U -#define V_T7_STOPBITS(x) ((x) << S_T7_STOPBITS) -#define G_T7_STOPBITS(x) (((x) >> S_T7_STOPBITS) & M_T7_STOPBITS) +#define S_T7_UART_STOPBITS 25 +#define M_T7_UART_STOPBITS 0x3U +#define V_T7_UART_STOPBITS(x) ((x) << S_T7_UART_STOPBITS) +#define G_T7_UART_STOPBITS(x) (((x) >> S_T7_UART_STOPBITS) & M_T7_UART_STOPBITS) -#define S_T7_PARITY 23 -#define M_T7_PARITY 0x3U -#define V_T7_PARITY(x) ((x) << S_T7_PARITY) -#define G_T7_PARITY(x) (((x) >> S_T7_PARITY) & M_T7_PARITY) +#define S_T7_UART_PARITY 23 +#define M_T7_UART_PARITY 0x3U +#define V_T7_UART_PARITY(x) ((x) << S_T7_UART_PARITY) +#define G_T7_UART_PARITY(x) (((x) >> S_T7_UART_PARITY) & M_T7_UART_PARITY) -#define S_T7_DATABITS 19 -#define M_T7_DATABITS 0xfU -#define V_T7_DATABITS(x) ((x) << S_T7_DATABITS) -#define G_T7_DATABITS(x) (((x) >> S_T7_DATABITS) & M_T7_DATABITS) +#define S_T7_UART_DATABITS 19 +#define M_T7_UART_DATABITS 0xfU +#define V_T7_UART_DATABITS(x) ((x) << S_T7_UART_DATABITS) +#define G_T7_UART_DATABITS(x) (((x) >> S_T7_UART_DATABITS) & M_T7_UART_DATABITS) #define S_T7_UART_CLKDIV 0 #define M_T7_UART_CLKDIV 0x3ffffU @@ -46607,13 +47199,13 @@ #define V_T7_SE_CNT_MISMATCH_0(x) ((x) << S_T7_SE_CNT_MISMATCH_0) #define F_T7_SE_CNT_MISMATCH_0 V_T7_SE_CNT_MISMATCH_0(1U) -#define S_ENABLE_CTX_3 7 -#define V_ENABLE_CTX_3(x) ((x) << S_ENABLE_CTX_3) -#define F_ENABLE_CTX_3 V_ENABLE_CTX_3(1U) +#define S_T7_ENABLE_CTX_3 7 +#define V_T7_ENABLE_CTX_3(x) ((x) << S_T7_ENABLE_CTX_3) +#define F_T7_ENABLE_CTX_3 V_T7_ENABLE_CTX_3(1U) -#define S_ENABLE_CTX_2 6 -#define V_ENABLE_CTX_2(x) ((x) << S_ENABLE_CTX_2) -#define F_ENABLE_CTX_2 V_ENABLE_CTX_2(1U) +#define S_T7_ENABLE_CTX_2 6 +#define V_T7_ENABLE_CTX_2(x) ((x) << S_T7_ENABLE_CTX_2) +#define F_T7_ENABLE_CTX_2 V_T7_ENABLE_CTX_2(1U) #define S_T7_ENABLE_CTX_1 5 #define V_T7_ENABLE_CTX_1(x) ((x) << S_T7_ENABLE_CTX_1) @@ -46623,13 +47215,13 @@ #define V_T7_ENABLE_CTX_0(x) ((x) << S_T7_ENABLE_CTX_0) #define F_T7_ENABLE_CTX_0 V_T7_ENABLE_CTX_0(1U) -#define S_ENABLE_ALN_SDC_ERR_3 3 -#define V_ENABLE_ALN_SDC_ERR_3(x) ((x) << S_ENABLE_ALN_SDC_ERR_3) -#define F_ENABLE_ALN_SDC_ERR_3 V_ENABLE_ALN_SDC_ERR_3(1U) +#define S_T7_ENABLE_ALN_SDC_ERR_3 3 +#define V_T7_ENABLE_ALN_SDC_ERR_3(x) ((x) << S_T7_ENABLE_ALN_SDC_ERR_3) +#define F_T7_ENABLE_ALN_SDC_ERR_3 V_T7_ENABLE_ALN_SDC_ERR_3(1U) -#define S_ENABLE_ALN_SDC_ERR_2 2 -#define V_ENABLE_ALN_SDC_ERR_2(x) ((x) << S_ENABLE_ALN_SDC_ERR_2) -#define F_ENABLE_ALN_SDC_ERR_2 V_ENABLE_ALN_SDC_ERR_2(1U) +#define S_T7_ENABLE_ALN_SDC_ERR_2 2 +#define V_T7_ENABLE_ALN_SDC_ERR_2(x) ((x) << S_T7_ENABLE_ALN_SDC_ERR_2) +#define F_T7_ENABLE_ALN_SDC_ERR_2 V_T7_ENABLE_ALN_SDC_ERR_2(1U) #define S_T7_ENABLE_ALN_SDC_ERR_1 1 #define V_T7_ENABLE_ALN_SDC_ERR_1(x) ((x) << S_T7_ENABLE_ALN_SDC_ERR_1) @@ -78548,6 +79140,17 @@ #define A_MAC_MTIP_MAC400G_0_MTIP_MAC_ADDR_1 0x38210 #define A_MAC_MTIP_MAC400G_0_MTIP_FRM_LENGTH 0x38214 #define A_MAC_MTIP_MAC400G_0_MTIP_RX_FIFO_SECTIONS 0x3821c + +#define S_T7_MAC_EMPTY 16 +#define M_T7_MAC_EMPTY 0xffffU +#define V_T7_MAC_EMPTY(x) ((x) << S_T7_MAC_EMPTY) +#define G_T7_MAC_EMPTY(x) (((x) >> S_T7_MAC_EMPTY) & M_T7_MAC_EMPTY) + +#define S_T7_MAC_AVAIL 0 +#define M_T7_MAC_AVAIL 0xffffU +#define V_T7_MAC_AVAIL(x) ((x) << S_T7_MAC_AVAIL) +#define G_T7_MAC_AVAIL(x) (((x) >> S_T7_MAC_AVAIL) & M_T7_MAC_AVAIL) + #define A_MAC_MTIP_MAC400G_0_MTIP_TX_FIFO_SECTIONS 0x38220 #define A_MAC_MTIP_MAC400G_0_MTIP_RX_FIFO_ALMOST_F_E 0x38224 #define A_MAC_MTIP_MAC400G_0_MTIP_TX_FIFO_ALMOST_F_E 0x38228 @@ -82543,7 +83146,6 @@ #define F_DMA_PL_RST_N V_DMA_PL_RST_N(1U) #define A_ARM_PLM_RID_CFG 0x4703c -#define A_ARM_PLM_EROM_CFG 0x47040 #define A_ARM_PL_ARM_HDR_CFG 0x4704c #define A_ARM_RC_INT_STATUS 0x4705c @@ -85733,20 +86335,7 @@ #define V_T7_ECC_UE_INT_CAUSE(x) ((x) << S_T7_ECC_UE_INT_CAUSE) #define F_T7_ECC_UE_INT_CAUSE V_T7_ECC_UE_INT_CAUSE(1U) -#define A_MC_P_ECC_UE_INT_ENABLE 0x49324 - -#define S_BIST_RSP_SRAM_UERR_ENABLE 0 -#define V_BIST_RSP_SRAM_UERR_ENABLE(x) ((x) << S_BIST_RSP_SRAM_UERR_ENABLE) -#define F_BIST_RSP_SRAM_UERR_ENABLE V_BIST_RSP_SRAM_UERR_ENABLE(1U) - -#define A_MC_P_ECC_UE_INT_CAUSE 0x49328 - -#define S_BIST_RSP_SRAM_UERR_CAUSE 0 -#define V_BIST_RSP_SRAM_UERR_CAUSE(x) ((x) << S_BIST_RSP_SRAM_UERR_CAUSE) -#define F_BIST_RSP_SRAM_UERR_CAUSE V_BIST_RSP_SRAM_UERR_CAUSE(1U) - #define A_T7_MC_P_ECC_STATUS 0x4932c -#define A_T7_MC_P_PHY_CTRL 0x49330 #define A_T7_MC_P_STATIC_CFG_STATUS 0x49334 #define S_DFIFREQRATIO 27 @@ -86100,6 +86689,7 @@ #define V_FLIP_BIT_POS0(x) ((x) << S_FLIP_BIT_POS0) #define G_FLIP_BIT_POS0(x) (((x) >> S_FLIP_BIT_POS0) & M_FLIP_BIT_POS0) +#define A_MC_REGB_DDRC_CH1_ECCSTAT 0x11608 #define A_MC_REGB_DDRC_CH1_ECCCTL 0x1160c #define A_MC_REGB_DDRC_CH1_ECCERRCNT 0x11610 #define A_MC_REGB_DDRC_CH1_ECCCADDR0 0x11614 diff --git a/sys/dev/cxgbe/crypto/t6_kern_tls.c b/sys/dev/cxgbe/crypto/t6_kern_tls.c index 454b2e264a0e..584e5015acfa 100644 --- a/sys/dev/cxgbe/crypto/t6_kern_tls.c +++ b/sys/dev/cxgbe/crypto/t6_kern_tls.c @@ -458,15 +458,15 @@ t6_tls_tag_alloc(if_t ifp, union if_snd_tag_alloc_params *params, } inp = params->tls.inp; + tp = intotcpcb(inp); INP_RLOCK(inp); - if (inp->inp_flags & INP_DROPPED) { + if (tp->t_flags & TF_DISCONNECTED) { INP_RUNLOCK(inp); error = ECONNRESET; goto failed; } tlsp->inp = inp; - tp = intotcpcb(inp); if (tp->t_flags & TF_REQ_TSTMP) { tlsp->using_timestamps = true; if ((tp->ts_offset & 0xfffffff) != 0) { @@ -501,7 +501,7 @@ t6_tls_tag_alloc(if_t ifp, union if_snd_tag_alloc_params *params, goto failed; } - if (inp->inp_flags & INP_DROPPED) { + if (tp->t_flags & TF_DISCONNECTED) { INP_RUNLOCK(inp); error = ECONNRESET; goto failed; diff --git a/sys/dev/cxgbe/crypto/t7_kern_tls.c b/sys/dev/cxgbe/crypto/t7_kern_tls.c index d9710b5bd13f..b6078b9b53b6 100644 --- a/sys/dev/cxgbe/crypto/t7_kern_tls.c +++ b/sys/dev/cxgbe/crypto/t7_kern_tls.c @@ -246,7 +246,7 @@ t7_tls_tag_alloc(struct ifnet *ifp, union if_snd_tag_alloc_params *params, inp = params->tls.inp; INP_RLOCK(inp); - if (inp->inp_flags & INP_DROPPED) { + if (intotcpcb(inp)->t_flags & TF_DISCONNECTED) { INP_RUNLOCK(inp); error = ECONNRESET; goto failed; diff --git a/sys/dev/cxgbe/cxgbei/cxgbei.c b/sys/dev/cxgbe/cxgbei/cxgbei.c index ccca45f5f761..4b341c9d37b2 100644 --- a/sys/dev/cxgbe/cxgbei/cxgbei.c +++ b/sys/dev/cxgbe/cxgbei/cxgbei.c @@ -499,10 +499,11 @@ do_rx_iscsi_ddp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) toep->ofld_rxq->rx_iscsi_ddp_octets += ip->ip_data_len; } + tp = intotcpcb(inp); INP_WLOCK(inp); - if (__predict_false(inp->inp_flags & INP_DROPPED)) { - CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), inp_flags 0x%x", - __func__, tid, pdu_len, inp->inp_flags); + if (__predict_false(tp->t_flags & TF_DISCONNECTED)) { + CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), t_flags 0x%x", + __func__, tid, pdu_len, tp->t_flags); INP_WUNLOCK(inp); icl_cxgbei_conn_pdu_free(NULL, ip); toep->ulpcb2 = NULL; @@ -513,7 +514,6 @@ do_rx_iscsi_ddp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) * T6+ does not report data PDUs received via DDP without F * set. This can result in gaps in the TCP sequence space. */ - tp = intotcpcb(inp); MPASS(chip_id(sc) >= CHELSIO_T6 || icp->icp_seq == tp->rcv_nxt); tp->rcv_nxt = icp->icp_seq + pdu_len; tp->t_rcvtime = ticks; @@ -652,10 +652,11 @@ do_rx_iscsi_cmp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) toep->ofld_rxq->rx_iscsi_data_digest_errors++; } + tp = intotcpcb(inp); INP_WLOCK(inp); - if (__predict_false(inp->inp_flags & INP_DROPPED)) { - CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), inp_flags 0x%x", - __func__, tid, pdu_len, inp->inp_flags); + if (__predict_false(tp->t_flags & TF_DISCONNECTED)) { + CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), t_flags 0x%x", + __func__, tid, pdu_len, tp->t_flags); INP_WUNLOCK(inp); icl_cxgbei_conn_pdu_free(NULL, ip); toep->ulpcb2 = NULL; @@ -663,8 +664,6 @@ do_rx_iscsi_cmp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) return (0); } - tp = intotcpcb(inp); - /* * If icc is NULL, the connection is being closed in * icl_cxgbei_conn_close(), just drop this data. diff --git a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c index 9cdfd0fb9652..09023b00248e 100644 --- a/sys/dev/cxgbe/cxgbei/icl_cxgbei.c +++ b/sys/dev/cxgbe/cxgbei/icl_cxgbei.c @@ -164,7 +164,7 @@ static kobj_method_t icl_cxgbei_methods[] = { KOBJMETHOD(icl_conn_task_done, icl_cxgbei_conn_task_done), KOBJMETHOD(icl_conn_transfer_setup, icl_cxgbei_conn_transfer_setup), KOBJMETHOD(icl_conn_transfer_done, icl_cxgbei_conn_transfer_done), - { 0, 0 } + KOBJMETHOD_END }; DEFINE_CLASS(icl_cxgbei, icl_cxgbei_methods, sizeof(struct icl_cxgbei_conn)); @@ -434,6 +434,7 @@ icl_cxgbei_tx_main(void *arg) struct toepcb *toep = icc->toep; struct socket *so = ic->ic_socket; struct inpcb *inp = sotoinpcb(so); + struct tcpcb *tp = intotcpcb(inp); struct icl_pdu *ip; struct mbuf *m; struct mbufq mq; @@ -476,7 +477,7 @@ icl_cxgbei_tx_main(void *arg) INP_WLOCK(inp); ICL_CONN_UNLOCK(ic); - if (__predict_false(inp->inp_flags & INP_DROPPED) || + if (__predict_false(tp->t_flags & TF_DISCONNECTED) || __predict_false((toep->flags & TPF_ATTACHED) == 0)) { mbufq_drain(&mq); } else { @@ -621,7 +622,7 @@ icl_cxgbei_conn_pdu_append_bio(struct icl_conn *ic, struct icl_pdu *ip, { struct icl_cxgbei_pdu *icp = ip_to_icp(ip); struct mbuf *m, *m_tail; - vm_offset_t vaddr; + void *vaddr; size_t page_offset, todo, mtodo; bool mapped; int i; @@ -809,7 +810,7 @@ icl_cxgbei_conn_pdu_get_bio(struct icl_conn *ic, struct icl_pdu *ip, size_t pdu_off, struct bio *bp, size_t bio_off, size_t len) { struct icl_cxgbei_pdu *icp = ip_to_icp(ip); - vm_offset_t vaddr; + void *vaddr; size_t page_offset, todo; bool mapped; int i; @@ -1080,7 +1081,7 @@ icl_cxgbei_conn_handoff(struct icl_conn *ic, int fd) inp = sotoinpcb(so); INP_WLOCK(inp); tp = intotcpcb(inp); - if (inp->inp_flags & INP_DROPPED) { + if (tp->t_flags & TF_DISCONNECTED) { INP_WUNLOCK(inp); error = ENOTCONN; goto out; @@ -1334,6 +1335,7 @@ icl_cxgbei_conn_task_setup(struct icl_conn *ic, struct icl_pdu *ip, struct cxgbei_ddp_state *ddp; struct ppod_reservation *prsv; struct inpcb *inp; + struct tcpcb *tp; struct mbufq mq; uint32_t itt; int rc = 0; @@ -1421,8 +1423,9 @@ no_ddp: * detached already. */ inp = sotoinpcb(ic->ic_socket); + tp = intotcpcb(inp); INP_WLOCK(inp); - if ((inp->inp_flags & INP_DROPPED) != 0) { + if ((tp->t_flags & TF_DISCONNECTED) != 0) { INP_WUNLOCK(inp); mbufq_drain(&mq); t4_free_page_pods(prsv); @@ -1497,6 +1500,7 @@ icl_cxgbei_conn_transfer_setup(struct icl_conn *ic, struct icl_pdu *ip, struct ppod_reservation *prsv; struct ctl_sg_entry *sgl, sg_entry; struct inpcb *inp; + struct tcpcb *tp; struct mbufq mq; int sg_entries = ctsio->kern_sg_entries; uint32_t ttt; @@ -1597,9 +1601,10 @@ no_ddp: return (ECONNRESET); } inp = sotoinpcb(ic->ic_socket); + tp = intotcpcb(inp); INP_WLOCK(inp); ICL_CONN_UNLOCK(ic); - if ((inp->inp_flags & INP_DROPPED) != 0) { + if ((tp->t_flags & TF_DISCONNECTED) != 0) { INP_WUNLOCK(inp); mbufq_drain(&mq); t4_free_page_pods(prsv); diff --git a/sys/dev/cxgbe/firmware/t7fw_cfg.txt b/sys/dev/cxgbe/firmware/t7fw_cfg.txt index 499af3675bd9..70b05da04a23 100644 --- a/sys/dev/cxgbe/firmware/t7fw_cfg.txt +++ b/sys/dev/cxgbe/firmware/t7fw_cfg.txt @@ -114,7 +114,8 @@ reg[0x7dc0] = 0x0e2f8849 # TP_SHIFT_CNT - reg[0x46004] = 0x3/0x3 #Crypto core reset + reg[0x46004] = 0x3/0x3 # Crypto core reset + reg[0x46000] = 0xa/0xe # 16K ESH Hi Extraction window #Tick granularities in kbps tsch_ticks = 100000, 10000, 1000, 10 @@ -192,14 +193,15 @@ reg[0x19250] = 0x0/0x3 # Termimate_msg = 0 # Terminate_with_err = 0 - gc_disable = 3 # 3 - disable gc for hma/mc1 and mc0, + #Enabling GC for HMA + gc_disable = 1 # 3 - disable gc for hma/mc1 and mc0, # 2 - disable gc for mc1/hma enable mc0, # 1 - enable gc for mc1/hma disable mc0, # 0 - enable gc for mc1/hma and for mc0, # default gc enabled. # HMA configuration (uncomment following lines to enable HMA) - hma_size = 92 # Size (in MBs) of host memory expected + hma_size = 128 # Size (in MBs) of host memory expected hma_regions = iscsi,rrq,tls,ddp,pmrx,stag,pbl,rq # What all regions to place in host memory #mc[0]=0 @@ -429,7 +431,7 @@ nethofld = 1024 # number of user mode ethernet flow contexts ncrypto_lookaside = 32 nclip = 320 # number of clip region entries - nfilter = 480 # number of filter region entries + nfilter = 448 # number of filter region entries nserver = 480 # number of server region entries nhash = 12288 # number of hash region entries nhpfilter = 64 # number of high priority filter region entries @@ -505,12 +507,20 @@ nfilter = 16 # number of filter region entries #nhpfilter = 16 # number of high priority filter region entries niqflint = 34 # NPORTS*NCPUS + NMSIX_EXTRA - nethctrl = 32 # NPORTS*NCPUS - neq = 64 # NPORTS*NCPUS * 2 (FL, ETHCTRL/TX) + nethctrl = 128 # NPORTS*NCPUS + neq = 256 # NPORTS*NCPUS * 2 (FL, ETHCTRL/TX) nserver = 16 nhash = 1024 tp_l2t = 512 protocol = nic_vm, ofld, rddp, rdmac, tlskeys, ipsec_inline, rocev2, nvme_tcp + tp_ddp = 1 + tp_ddp_iscsi = 1 + tp_tls_key = 1 + tp_stag = 1 + tp_pbl = 3 + tp_rq = 4 + tp_rrq = 2 + tp_srq = 96 # The following function, 1023, is not an actual PCIE function but is used to # configure and reserve firmware internal resources that come from the global @@ -523,7 +533,7 @@ cmask = all # access to all channels pmask = all # access to all four ports ... nexactf = 8 # NPORTS + DCBX + - nfilter = 16 # number of filter region entries + nfilter = 48 # number of filter region entries #nhpfilter = 0 # number of high priority filter region entries @@ -594,7 +604,7 @@ # Bytes) # [port "0"] - #dcb = ppp, dcbx, b2b # configure for DCB PPP and enable DCBX offload + #dcb = ppp, dcbx # configure for DCB PPP and enable DCBX offload hwm = 30 lwm = 15 dwm = 30 @@ -604,7 +614,7 @@ [port "1"] - #dcb = ppp, dcbx, b2b + #dcb = ppp, dcbx hwm = 30 lwm = 15 dwm = 30 @@ -613,7 +623,7 @@ dcb_app_tlv[2] = 3260, socketnum, 5 [port "2"] - #dcb = ppp, dcbx, b2b # configure for DCB PPP and enable DCBX offload + #dcb = ppp, dcbx # configure for DCB PPP and enable DCBX offload hwm = 30 lwm = 15 dwm = 30 @@ -623,7 +633,7 @@ [port "3"] - #dcb = ppp, dcbx, b2b + #dcb = ppp, dcbx hwm = 30 lwm = 15 dwm = 30 @@ -633,7 +643,7 @@ [fini] version = 0x1425001d - checksum = 0x684e23fb + checksum = 0x3671da3b # Total resources used by above allocations: # Virtual Interfaces: 104 diff --git a/sys/dev/cxgbe/firmware/t7fw_cfg_uwire.txt b/sys/dev/cxgbe/firmware/t7fw_cfg_uwire.txt index 0bca1c194af8..b1f5129238eb 100644 --- a/sys/dev/cxgbe/firmware/t7fw_cfg_uwire.txt +++ b/sys/dev/cxgbe/firmware/t7fw_cfg_uwire.txt @@ -114,7 +114,8 @@ reg[0x7dc0] = 0x0e2f8849 # TP_SHIFT_CNT - reg[0x46004] = 0x3/0x3 #Crypto core reset + reg[0x46004] = 0x3/0x3 # Crypto core reset + reg[0x46000] = 0xa/0xe # 16K ESH Hi Extraction window #Tick granularities in kbps tsch_ticks = 100000, 10000, 1000, 10 @@ -192,14 +193,15 @@ reg[0x19250] = 0x0/0x3 # Termimate_msg = 0 # Terminate_with_err = 0 - gc_disable = 3 # 3 - disable gc for hma/mc1 and mc0, + #Enabling GC for HMA + gc_disable = 1 # 3 - disable gc for hma/mc1 and mc0, # 2 - disable gc for mc1/hma enable mc0, # 1 - enable gc for mc1/hma disable mc0, # 0 - enable gc for mc1/hma and for mc0, # default gc enabled. # HMA configuration (uncomment following lines to enable HMA) - hma_size = 92 # Size (in MBs) of host memory expected + hma_size = 128 # Size (in MBs) of host memory expected hma_regions = iscsi,rrq,tls,ddp,pmrx,stag,pbl,rq # What all regions to place in host memory #mc[0]=0 @@ -429,7 +431,7 @@ nethofld = 1024 # number of user mode ethernet flow contexts ncrypto_lookaside = 32 nclip = 320 # number of clip region entries - nfilter = 480 # number of filter region entries + nfilter = 448 # number of filter region entries nserver = 480 # number of server region entries nhash = 12288 # number of hash region entries nhpfilter = 64 # number of high priority filter region entries @@ -505,12 +507,20 @@ nfilter = 16 # number of filter region entries #nhpfilter = 16 # number of high priority filter region entries niqflint = 34 # NPORTS*NCPUS + NMSIX_EXTRA - nethctrl = 32 # NPORTS*NCPUS - neq = 64 # NPORTS*NCPUS * 2 (FL, ETHCTRL/TX) + nethctrl = 128 # NPORTS*NCPUS + neq = 256 # NPORTS*NCPUS * 2 (FL, ETHCTRL/TX) nserver = 16 nhash = 1024 tp_l2t = 512 protocol = nic_vm, ofld, rddp, rdmac, tlskeys, ipsec_inline, rocev2, nvme_tcp + tp_ddp = 1 + tp_ddp_iscsi = 1 + tp_tls_key = 1 + tp_stag = 1 + tp_pbl = 3 + tp_rq = 4 + tp_rrq = 2 + tp_srq = 96 # The following function, 1023, is not an actual PCIE function but is used to # configure and reserve firmware internal resources that come from the global @@ -523,7 +533,7 @@ cmask = all # access to all channels pmask = all # access to all four ports ... nexactf = 8 # NPORTS + DCBX + - nfilter = 16 # number of filter region entries + nfilter = 48 # number of filter region entries #nhpfilter = 0 # number of high priority filter region entries @@ -633,7 +643,7 @@ [fini] version = 0x1425001d - checksum = 0x5cab62d4 + checksum = 0x96513217 # Total resources used by above allocations: # Virtual Interfaces: 104 diff --git a/sys/dev/cxgbe/iw_cxgbe/qp.c b/sys/dev/cxgbe/iw_cxgbe/qp.c index cbf4bae00a60..372fc5418b91 100644 --- a/sys/dev/cxgbe/iw_cxgbe/qp.c +++ b/sys/dev/cxgbe/iw_cxgbe/qp.c @@ -64,7 +64,7 @@ struct cpl_set_tcb_rpl; #include "iw_cxgbe.h" #include "user.h" -static int creds(struct toepcb *toep, struct inpcb *inp, size_t wrsize); +static int creds(struct toepcb *toep, struct tcpcb *tp, size_t wrsize); static int max_fr_immd = T4_MAX_FR_IMMD;//SYSCTL parameter later... static int alloc_ird(struct c4iw_dev *dev, u32 ird) @@ -1149,7 +1149,7 @@ static void post_terminate(struct c4iw_qp *qhp, struct t4_cqe *err_cqe, term->ecode = qhp->attr.ecode; } else build_term_codes(err_cqe, &term->layer_etype, &term->ecode); - ret = creds(toep, inp, sizeof(*wqe)); + ret = creds(toep, tp, sizeof(*wqe)); if (ret) { free_wrqe(wr); return; @@ -1253,8 +1253,7 @@ rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp, struct c4iw_ep *ep) int ret; struct wrqe *wr; struct socket *so = ep->com.so; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp = intotcpcb(inp); + struct tcpcb *tp = intotcpcb(sotoinpcb(so)); struct toepcb *toep = tp->t_toe; KASSERT(rhp == qhp->rhp && ep == qhp->ep, ("%s: EDOOFUS", __func__)); @@ -1277,7 +1276,7 @@ rdma_fini(struct c4iw_dev *rhp, struct c4iw_qp *qhp, struct c4iw_ep *ep) c4iw_init_wr_wait(&ep->com.wr_wait); - ret = creds(toep, inp, sizeof(*wqe)); + ret = creds(toep, tp, sizeof(*wqe)); if (ret) { free_wrqe(wr); return ret; @@ -1315,14 +1314,14 @@ static void build_rtr_msg(u8 p2p_type, struct fw_ri_init *init) } static int -creds(struct toepcb *toep, struct inpcb *inp, size_t wrsize) +creds(struct toepcb *toep, struct tcpcb *tp, size_t wrsize) { struct ofld_tx_sdesc *txsd; CTR3(KTR_IW_CXGBE, "%s:creB %p %u", __func__, toep , wrsize); - INP_WLOCK(inp); - if ((inp->inp_flags & INP_DROPPED) != 0) { - INP_WUNLOCK(inp); + INP_WLOCK(tptoinpcb(tp)); + if (tp->t_flags & TF_DISCONNECTED) { + INP_WUNLOCK(tptoinpcb(tp)); return (EINVAL); } txsd = &toep->txsd[toep->txsd_pidx]; @@ -1336,7 +1335,7 @@ creds(struct toepcb *toep, struct inpcb *inp, size_t wrsize) if (__predict_false(++toep->txsd_pidx == toep->txsd_total)) toep->txsd_pidx = 0; toep->txsd_avail--; - INP_WUNLOCK(inp); + INP_WUNLOCK(tptoinpcb(tp)); CTR5(KTR_IW_CXGBE, "%s:creE %p %u %u %u", __func__, toep , txsd->tx_credits, toep->tx_credits, toep->txsd_pidx); return (0); @@ -1351,8 +1350,7 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp) struct c4iw_rdev *rdev = &qhp->rhp->rdev; struct adapter *sc = rdev->adap; struct socket *so = ep->com.so; - struct inpcb *inp = sotoinpcb(so); - struct tcpcb *tp = intotcpcb(inp); + struct tcpcb *tp = intotcpcb(sotoinpcb(so)); struct toepcb *toep = tp->t_toe; CTR5(KTR_IW_CXGBE, "%s qhp %p qid 0x%x ep %p tid %u", __func__, qhp, @@ -1416,7 +1414,7 @@ static int rdma_init(struct c4iw_dev *rhp, struct c4iw_qp *qhp) c4iw_init_wr_wait(&ep->com.wr_wait); - ret = creds(toep, inp, sizeof(*wqe)); + ret = creds(toep, tp, sizeof(*wqe)); if (ret) { free_wrqe(wr); free_ird(rhp, qhp->attr.max_ird); diff --git a/sys/dev/cxgbe/nvmf/nvmf_che.c b/sys/dev/cxgbe/nvmf/nvmf_che.c index 5c2174b8a40b..be54e7bebfea 100644 --- a/sys/dev/cxgbe/nvmf/nvmf_che.c +++ b/sys/dev/cxgbe/nvmf/nvmf_che.c @@ -555,6 +555,7 @@ che_write_adapter_mem(struct nvmf_che_qpair *qp, uint32_t addr, uint32_t len, struct toepcb *toep = qp->toep; struct socket *so = qp->so; struct inpcb *inp = sotoinpcb(so); + struct tcpcb *tp = intotcpcb(inp); struct mbufq mq; int error; @@ -568,7 +569,7 @@ che_write_adapter_mem(struct nvmf_che_qpair *qp, uint32_t addr, uint32_t len, goto error; INP_WLOCK(inp); - if ((inp->inp_flags & INP_DROPPED) != 0) { + if ((tp->t_flags & TF_DISCONNECTED) != 0) { INP_WUNLOCK(inp); error = ECONNRESET; goto error; @@ -862,12 +863,13 @@ nvmf_che_write_pdu(struct nvmf_che_qpair *qp, struct mbuf *m) struct epoch_tracker et; struct socket *so = qp->so; struct inpcb *inp = sotoinpcb(so); + struct tcpcb *tp = intotcpcb(inp); struct toepcb *toep = qp->toep; CURVNET_SET(so->so_vnet); NET_EPOCH_ENTER(et); INP_WLOCK(inp); - if (__predict_false(inp->inp_flags & INP_DROPPED) || + if (__predict_false(tp->t_flags & TF_DISCONNECTED) || __predict_false((toep->flags & TPF_ATTACHED) == 0)) { m_freem(m); } else { @@ -2052,10 +2054,11 @@ do_nvmt_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) ("%s: payload length mismatch", __func__)); inp = toep->inp; + tp = intotcpcb(inp); INP_WLOCK(inp); - if (inp->inp_flags & INP_DROPPED) { - CTR(KTR_CXGBE, "%s: tid %u, rx (%d bytes), inp_flags 0x%x", - __func__, tid, len, inp->inp_flags); + if (tp->t_flags & TF_DISCONNECTED) { + CTR(KTR_CXGBE, "%s: tid %u, rx (%d bytes), t_flags 0x%x", + __func__, tid, len, tp->t_flags); INP_WUNLOCK(inp); m_freem(m); return (0); @@ -2070,7 +2073,6 @@ do_nvmt_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) mbufq_enqueue(&qp->rx_data, m); SOCKBUF_UNLOCK(&so->so_rcv); - tp = intotcpcb(inp); tp->t_rcvtime = ticks; #ifdef VERBOSE_TRACES @@ -2092,6 +2094,7 @@ do_nvmt_cmp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) struct nvmf_che_qpair *qp = toep->ulpcb; struct socket *so = qp->so; struct inpcb *inp = toep->inp; + struct tcpcb *tp = intotcpcb(inp); u_int hlen __diagused; bool empty; @@ -2107,9 +2110,9 @@ do_nvmt_cmp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) ("%s: payload length mismatch", __func__)); INP_WLOCK(inp); - if (inp->inp_flags & INP_DROPPED) { - CTR(KTR_CXGBE, "%s: tid %u, rx (hlen %u), inp_flags 0x%x", - __func__, tid, hlen, inp->inp_flags); + if (tp->t_flags & TF_DISCONNECTED) { + CTR(KTR_CXGBE, "%s: tid %u, rx (hlen %u), t_flags 0x%x", + __func__, tid, hlen, tp->t_flags); INP_WUNLOCK(inp); m_freem(m); return (0); @@ -2505,7 +2508,7 @@ che_allocate_qpair(bool controller, const nvlist_t *nvl) inp = sotoinpcb(so); INP_WLOCK(inp); tp = intotcpcb(inp); - if (inp->inp_flags & INP_DROPPED) { + if (tp->t_flags & TF_DISCONNECTED) { INP_WUNLOCK(inp); free(qp->fl_cid_set, M_NVMF_CHE); free(qp->fl_cids, M_NVMF_CHE); @@ -2602,6 +2605,7 @@ che_allocate_qpair(bool controller, const nvlist_t *nvl) free(qp->fl_cids, M_NVMF_CHE); free(qp->open_fl_ttags, M_NVMF_CHE); free(qp, M_NVMF_CHE); + soclose(so); return (NULL); } diff --git a/sys/dev/cxgbe/t4_main.c b/sys/dev/cxgbe/t4_main.c index 3237c6649713..69ecfce1dade 100644 --- a/sys/dev/cxgbe/t4_main.c +++ b/sys/dev/cxgbe/t4_main.c @@ -128,7 +128,7 @@ device_method_t cxgbe_methods[] = { DEVMETHOD(device_probe, cxgbe_probe), DEVMETHOD(device_attach, cxgbe_attach), DEVMETHOD(device_detach, cxgbe_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t cxgbe_driver = { "cxgbe", @@ -144,7 +144,7 @@ static device_method_t vcxgbe_methods[] = { DEVMETHOD(device_probe, vcxgbe_probe), DEVMETHOD(device_attach, vcxgbe_attach), DEVMETHOD(device_detach, vcxgbe_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t vcxgbe_driver = { "vcxgbe", @@ -806,7 +806,7 @@ static int validate_mem_range(struct adapter *, uint32_t, uint32_t); static int fwmtype_to_hwmtype(int); static int validate_mt_off_len(struct adapter *, int, uint32_t, uint32_t, uint32_t *); -static int fixup_devlog_params(struct adapter *); +static int fixup_devlog_ncores_params(struct adapter *); static int cfg_itype_and_nqueues(struct adapter *, struct intrs_and_queues *); static int contact_firmware(struct adapter *); static int partition_resources(struct adapter *); @@ -900,6 +900,7 @@ static int sysctl_ulprx_la(SYSCTL_HANDLER_ARGS); static int sysctl_wcwr_stats(SYSCTL_HANDLER_ARGS); static int sysctl_cpus(SYSCTL_HANDLER_ARGS); static int sysctl_reset(SYSCTL_HANDLER_ARGS); +static int sysctl_tcb_cache(SYSCTL_HANDLER_ARGS); #ifdef TCP_OFFLOAD static int sysctl_tls(SYSCTL_HANDLER_ARGS); static int sysctl_tp_tick(SYSCTL_HANDLER_ARGS); @@ -1248,7 +1249,7 @@ t4_calibration(void *arg) sc = (struct adapter *)arg; - KASSERT(hw_all_ok(sc), ("!hw_all_ok at t4_calibration")); + KASSERT(!hw_off_limits(sc), ("hw_off_limits at t4_calibration")); hw = t4_read_reg64(sc, A_SGE_TIMESTAMP_LO); sbt = sbinuptime(); @@ -1424,7 +1425,7 @@ t4_attach(device_t dev) */ setup_memwin(sc); if (t4_init_devlog_ncores_params(sc, 0) == 0) - fixup_devlog_params(sc); + fixup_devlog_ncores_params(sc); make_dev_args_init(&mda); mda.mda_devsw = &t4_cdevsw; mda.mda_uid = UID_ROOT; @@ -4046,7 +4047,7 @@ t4_map_bar_2(struct adapter *sc) * request with an implicit doorbell. */ - rc = pmap_change_attr((vm_offset_t)sc->udbs_base, + rc = pmap_change_attr(__DEVOLATILE(void *, sc->udbs_base), rman_get_size(sc->udbs_res), PAT_WRITE_COMBINING); if (rc == 0) { clrbit(&sc->doorbells, DOORBELL_UDB); @@ -4564,11 +4565,15 @@ validate_mt_off_len(struct adapter *sc, int mtype, uint32_t off, uint32_t len, } static int -fixup_devlog_params(struct adapter *sc) +fixup_devlog_ncores_params(struct adapter *sc) { struct devlog_params *dparams = &sc->params.devlog; int rc; +#ifdef INVARIANTS + if (sc->params.ncores > 1) + MPASS(chip_id(sc) >= CHELSIO_T7); +#endif rc = validate_mt_off_len(sc, dparams->memtype, dparams->start, dparams->size, &dparams->addr); @@ -5558,7 +5563,7 @@ get_params__pre_init(struct adapter *sc) /* Read device log parameters. */ rc = -t4_init_devlog_ncores_params(sc, 1); if (rc == 0) - fixup_devlog_params(sc); + fixup_devlog_ncores_params(sc); else { device_printf(sc->dev, "failed to get devlog parameters: %d.\n", rc); @@ -5711,8 +5716,6 @@ get_params__post_init(struct adapter *sc) } if (sc->params.ncores > 1) { - MPASS(chip_id(sc) >= CHELSIO_T7); - param[0] = FW_PARAM_DEV(TID_QID_SEL_MASK); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 1, param, val); sc->params.tid_qid_sel_mask = rc == 0 ? val[0] : 0; @@ -8119,6 +8122,12 @@ t4_sysctls(struct adapter *sc) sysctl_wcwr_stats, "A", "write combined work requests"); } + if (chip_id(sc) >= CHELSIO_T7) { + SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tcb_cache", + CTLTYPE_INT | CTLFLAG_RW, sc, 0, sysctl_tcb_cache, "I", + "1 = enabled (default), 0 = disabled (for debug only)"); + } + #ifdef KERN_TLS if (is_ktls(sc)) { /* @@ -11587,7 +11596,7 @@ sysctl_tids(SYSCTL_HANDLER_ARGS) if (hashen) { if (x) sbuf_printf(sb, "%u-%u, ", t->tid_base, x - 1); - sbuf_printf(sb, "%u-%u", y, t->ntids - 1); + sbuf_printf(sb, "%u-%u", y, t->tid_base + t->ntids - 1); } else { sbuf_printf(sb, "%u-%u", t->tid_base, t->tid_base + t->ntids - 1); @@ -12204,6 +12213,40 @@ sysctl_reset(SYSCTL_HANDLER_ARGS) return (0); } +static int +sysctl_tcb_cache(SYSCTL_HANDLER_ARGS) +{ + struct adapter *sc = arg1; + u_int val, v; + int rc; + + mtx_lock(&sc->reg_lock); + if (hw_off_limits(sc)) { + rc = ENXIO; + goto done; + } + t4_tp_pio_read(sc, &v, 1, A_TP_CMM_CONFIG, 1); + mtx_unlock(&sc->reg_lock); + + val = v & F_GLFL ? 0 : 1; + rc = sysctl_handle_int(oidp, &val, 0, req); + if (rc != 0 || req->newptr == NULL) + return (rc); + if (val == 0) + v |= F_GLFL; + else + v &= ~F_GLFL; + + mtx_lock(&sc->reg_lock); + if (hw_off_limits(sc)) + rc = ENXIO; + else + t4_tp_pio_write(sc, &v, 1, A_TP_CMM_CONFIG, 1); +done: + mtx_unlock(&sc->reg_lock); + return (rc); +} + #ifdef TCP_OFFLOAD static int sysctl_tls(SYSCTL_HANDLER_ARGS) diff --git a/sys/dev/cxgbe/t4_netmap.c b/sys/dev/cxgbe/t4_netmap.c index 0135bec6e2c1..a858867239c6 100644 --- a/sys/dev/cxgbe/t4_netmap.c +++ b/sys/dev/cxgbe/t4_netmap.c @@ -606,10 +606,8 @@ cxgbe_netmap_split_rss(struct adapter *sc, struct vi_info *vi, (nm_state == NM_OFF && nm_kring_pending_on(kring))) { MPASS(nm_rxq->iq_cntxt_id != INVALID_NM_RXQ_CNTXT_ID); nactive[j]++; - if (dq[j] == -1) { + if (dq[j] == -1) dq[j] = nm_rxq->iq_abs_id; - break; - } } } diff --git a/sys/dev/cxgbe/t4_sge.c b/sys/dev/cxgbe/t4_sge.c index e9754ace27c2..07e4165db4a0 100644 --- a/sys/dev/cxgbe/t4_sge.c +++ b/sys/dev/cxgbe/t4_sge.c @@ -828,12 +828,17 @@ t4_tweak_chip_settings(struct adapter *sc) t4_set_reg_field(sc, A_SGE_ITP_CONTROL, m, v); if (sc->debug_flags & DF_DISABLE_TCB_CACHE) { - m = V_RDTHRESHOLD(M_RDTHRESHOLD) | F_WRTHRTHRESHEN | - V_WRTHRTHRESH(M_WRTHRTHRESH); t4_tp_pio_read(sc, &v, 1, A_TP_CMM_CONFIG, 1); - v &= ~m; - v |= V_RDTHRESHOLD(1) | F_WRTHRTHRESHEN | - V_WRTHRTHRESH(16); + if (chip_id(sc) >= CHELSIO_T7) { + v |= F_GLFL; + } else { + m = V_RDTHRESHOLD(M_RDTHRESHOLD) | + F_WRTHRTHRESHEN | + V_WRTHRTHRESH(M_WRTHRTHRESH); + v &= ~m; + v |= V_RDTHRESHOLD(1) | F_WRTHRTHRESHEN | + V_WRTHRTHRESH(16); + } t4_tp_pio_write(sc, &v, 1, A_TP_CMM_CONFIG, 1); } } @@ -1548,16 +1553,13 @@ sort_before_lro(struct lro_ctrl *lro) } #endif -#define CGBE_SHIFT_SCALE 10 - static inline uint64_t -t4_tstmp_to_ns(struct adapter *sc, uint64_t lf) +t4_tstmp_to_ns(struct adapter *sc, uint64_t hw_tstmp) { struct clock_sync *cur, dcur; uint64_t hw_clocks; uint64_t hw_clk_div; sbintime_t sbt_cur_to_prev, sbt; - uint64_t hw_tstmp = lf & 0xfffffffffffffffULL; /* 60b, not 64b. */ seqc_t gen; for (;;) { @@ -1967,25 +1969,12 @@ get_segment_len(struct adapter *sc, struct sge_fl *fl, int plen) return (min(plen, len)); } -static int -eth_rx(struct adapter *sc, struct sge_rxq *rxq, const struct iq_desc *d, - u_int plen) +static void +handle_cpl_rx_pkt(struct adapter *sc, struct sge_rxq *rxq, + const struct cpl_rx_pkt *cpl, struct mbuf *m0) { - struct mbuf *m0; if_t ifp = rxq->ifp; - struct sge_fl *fl = &rxq->fl; - struct vi_info *vi = if_getsoftc(ifp); - const struct cpl_rx_pkt *cpl; -#if defined(INET) || defined(INET6) - struct lro_ctrl *lro = &rxq->lro; -#endif uint16_t err_vec, tnl_type, tnlhdr_len; - static const int sw_hashtype[4][2] = { - {M_HASHTYPE_NONE, M_HASHTYPE_NONE}, - {M_HASHTYPE_RSS_IPV4, M_HASHTYPE_RSS_IPV6}, - {M_HASHTYPE_RSS_TCP_IPV4, M_HASHTYPE_RSS_TCP_IPV6}, - {M_HASHTYPE_RSS_UDP_IPV4, M_HASHTYPE_RSS_UDP_IPV6}, - }; static const int sw_csum_flags[2][2] = { { /* IP, inner IP */ @@ -2015,43 +2004,6 @@ eth_rx(struct adapter *sc, struct sge_rxq *rxq, const struct iq_desc *d, }, }; - MPASS(plen > sc->params.sge.fl_pktshift); - if (vi->pfil != NULL && PFIL_HOOKED_IN(vi->pfil) && - __predict_true((fl->flags & FL_BUF_RESUME) == 0)) { - struct fl_sdesc *sd = &fl->sdesc[fl->cidx]; - caddr_t frame; - int rc, slen; - - slen = get_segment_len(sc, fl, plen) - - sc->params.sge.fl_pktshift; - frame = sd->cl + fl->rx_offset + sc->params.sge.fl_pktshift; - CURVNET_SET_QUIET(if_getvnet(ifp)); - rc = pfil_mem_in(vi->pfil, frame, slen, ifp, &m0); - CURVNET_RESTORE(); - if (rc == PFIL_DROPPED || rc == PFIL_CONSUMED) { - skip_fl_payload(sc, fl, plen); - return (0); - } - if (rc == PFIL_REALLOCED) { - skip_fl_payload(sc, fl, plen); - goto have_mbuf; - } - } - - m0 = get_fl_payload(sc, fl, plen); - if (__predict_false(m0 == NULL)) - return (ENOMEM); - - m0->m_pkthdr.len -= sc->params.sge.fl_pktshift; - m0->m_len -= sc->params.sge.fl_pktshift; - m0->m_data += sc->params.sge.fl_pktshift; - -have_mbuf: - m0->m_pkthdr.rcvif = ifp; - M_HASHTYPE_SET(m0, sw_hashtype[d->rss.hash_type][d->rss.ipv6]); - m0->m_pkthdr.flowid = be32toh(d->rss.hash_val); - - cpl = (const void *)(&d->rss + 1); if (sc->params.tp.rx_pkt_encap) { const uint16_t ev = be16toh(cpl->err_vec); @@ -2136,23 +2088,79 @@ have_mbuf: rxq->vlan_extraction++; } } +} + +static int +eth_rx(struct adapter *sc, struct sge_rxq *rxq, const struct iq_desc *d, + u_int plen) +{ + struct mbuf *m0; + if_t ifp = rxq->ifp; + struct sge_fl *fl = &rxq->fl; + struct vi_info *vi = if_getsoftc(ifp); +#if defined(INET) || defined(INET6) + struct lro_ctrl *lro = &rxq->lro; +#endif + int rc; + const uint8_t fl_pktshift = sc->params.sge.fl_pktshift; + static const uint8_t sw_hashtype[4][2] = { + {M_HASHTYPE_NONE, M_HASHTYPE_NONE}, + {M_HASHTYPE_RSS_IPV4, M_HASHTYPE_RSS_IPV6}, + {M_HASHTYPE_RSS_TCP_IPV4, M_HASHTYPE_RSS_TCP_IPV6}, + {M_HASHTYPE_RSS_UDP_IPV4, M_HASHTYPE_RSS_UDP_IPV6}, + }; + + MPASS(plen > fl_pktshift); + if (vi->pfil != NULL && PFIL_HOOKED_IN(vi->pfil) && + __predict_true((fl->flags & FL_BUF_RESUME) == 0)) { + struct fl_sdesc *sd = &fl->sdesc[fl->cidx]; + caddr_t frame; + const int slen = get_segment_len(sc, fl, plen) - fl_pktshift; + + frame = sd->cl + fl->rx_offset + fl_pktshift; + CURVNET_SET_QUIET(if_getvnet(ifp)); + rc = pfil_mem_in(vi->pfil, frame, slen, ifp, &m0); + CURVNET_RESTORE(); + if (rc == PFIL_DROPPED || rc == PFIL_CONSUMED) { + skip_fl_payload(sc, fl, plen); + return (0); + } + if (rc == PFIL_REALLOCED) { + skip_fl_payload(sc, fl, plen); + goto have_mbuf; + } + } + + m0 = get_fl_payload(sc, fl, plen); + if (__predict_false(m0 == NULL)) + return (ENOMEM); + m0->m_pkthdr.len -= fl_pktshift; + m0->m_len -= fl_pktshift; + m0->m_data += fl_pktshift; +have_mbuf: + m0->m_pkthdr.rcvif = ifp; + M_HASHTYPE_SET(m0, sw_hashtype[d->rss.hash_type][d->rss.ipv6]); + m0->m_pkthdr.flowid = be32toh(d->rss.hash_val); +#ifdef NUMA + m0->m_pkthdr.numa_domain = if_getnumadomain(ifp); +#endif if (rxq->iq.flags & IQ_RX_TIMESTAMP) { /* - * Fill up rcv_tstmp but do not set M_TSTMP as - * long as we get a non-zero back from t4_tstmp_to_ns(). + * Fill up rcv_tstmp and set M_TSTMP if we get a a non-zero back + * from t4_tstmp_to_ns(). The descriptor has a 60b timestamp. */ m0->m_pkthdr.rcv_tstmp = t4_tstmp_to_ns(sc, - be64toh(d->rsp.u.last_flit)); + be64toh(d->rsp.u.last_flit) & 0x0fffffffffffffffULL); if (m0->m_pkthdr.rcv_tstmp != 0) m0->m_flags |= M_TSTMP; } -#ifdef NUMA - m0->m_pkthdr.numa_domain = if_getnumadomain(ifp); -#endif + handle_cpl_rx_pkt(sc, rxq, (const void *)(&d->rss + 1), m0); + #if defined(INET) || defined(INET6) - if (rxq->iq.flags & IQ_LRO_ENABLED && tnl_type == 0 && + if (rxq->iq.flags & IQ_LRO_ENABLED && + (m0->m_pkthdr.rsstype & M_HASHTYPE_INNER) == 0 && (M_HASHTYPE_GET(m0) == M_HASHTYPE_RSS_TCP_IPV4 || M_HASHTYPE_GET(m0) == M_HASHTYPE_RSS_TCP_IPV6)) { if (sort_before_lro(lro)) { @@ -4364,18 +4372,17 @@ qsize_to_fthresh(int qsize) static int ctrl_eq_alloc(struct adapter *sc, struct sge_eq *eq, int idx) { - int rc, cntxt_id, core; + int rc, cntxt_id; struct fw_eq_ctrl_cmd c; int qsize = eq->sidx + sc->params.sge.spg_len / EQ_ESIZE; - core = sc->params.tid_qid_sel_mask != 0 ? idx % sc->params.ncores : 0; bzero(&c, sizeof(c)); c.op_to_vfn = htobe32(V_FW_CMD_OP(FW_EQ_CTRL_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE | F_FW_CMD_EXEC | V_FW_EQ_CTRL_CMD_PFN(sc->pf) | V_FW_EQ_CTRL_CMD_VFN(0)); c.alloc_to_len16 = htobe32(F_FW_EQ_CTRL_CMD_ALLOC | - V_FW_EQ_CTRL_CMD_COREGROUP(core) | + V_FW_EQ_CTRL_CMD_COREGROUP(idx % sc->params.ncores) | F_FW_EQ_CTRL_CMD_EQSTART | FW_LEN16(c)); c.cmpliqid_eqid = htonl(V_FW_EQ_CTRL_CMD_CMPLIQID(eq->iqid)); c.physeqid_pkd = htobe32(0); @@ -4412,18 +4419,17 @@ ctrl_eq_alloc(struct adapter *sc, struct sge_eq *eq, int idx) static int eth_eq_alloc(struct adapter *sc, struct vi_info *vi, struct sge_eq *eq, int idx) { - int rc, cntxt_id, core; + int rc, cntxt_id; struct fw_eq_eth_cmd c; int qsize = eq->sidx + sc->params.sge.spg_len / EQ_ESIZE; - core = sc->params.ncores > 1 ? idx % sc->params.ncores : 0; bzero(&c, sizeof(c)); c.op_to_vfn = htobe32(V_FW_CMD_OP(FW_EQ_ETH_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE | F_FW_CMD_EXEC | V_FW_EQ_ETH_CMD_PFN(sc->pf) | V_FW_EQ_ETH_CMD_VFN(0)); c.alloc_to_len16 = htobe32(F_FW_EQ_ETH_CMD_ALLOC | - V_FW_EQ_ETH_CMD_COREGROUP(core) | + V_FW_EQ_ETH_CMD_COREGROUP(idx % sc->params.ncores) | F_FW_EQ_ETH_CMD_EQSTART | FW_LEN16(c)); c.autoequiqe_to_viid = htobe32(F_FW_EQ_ETH_CMD_AUTOEQUIQE | F_FW_EQ_ETH_CMD_AUTOEQUEQE | V_FW_EQ_ETH_CMD_VIID(vi->viid)); @@ -5461,7 +5467,7 @@ csum_to_ctrl(struct adapter *sc, struct mbuf *m) uint64_t ctrl; int csum_type, l2hlen, l3hlen; int x, y; - static const int csum_types[3][2] = { + static const uint8_t csum_types[3][2] = { {TX_CSUM_TCPIP, TX_CSUM_TCPIP6}, {TX_CSUM_UDPIP, TX_CSUM_UDPIP6}, {TX_CSUM_IP, 0} diff --git a/sys/dev/cxgbe/tom/t4_connect.c b/sys/dev/cxgbe/tom/t4_connect.c index c236ee060bc2..e5f6053e2cb6 100644 --- a/sys/dev/cxgbe/tom/t4_connect.c +++ b/sys/dev/cxgbe/tom/t4_connect.c @@ -78,6 +78,7 @@ do_act_establish(struct sge_iq *iq, const struct rss_header *rss, u_int atid = G_TID_TID(ntohl(cpl->tos_atid)); struct toepcb *toep = lookup_atid(sc, atid); struct inpcb *inp = toep->inp; + struct tcpcb *tp = intotcpcb(inp); KASSERT(m == NULL, ("%s: wasn't expecting payload", __func__)); KASSERT(toep->tid == atid, ("%s: toep tid/atid mismatch", __func__)); @@ -95,7 +96,7 @@ do_act_establish(struct sge_iq *iq, const struct rss_header *rss, toep->ctrlq = &sc->sge.ctrlq[toep->params.ctrlq_idx]; } - if (inp->inp_flags & INP_DROPPED) { + if (tp->t_flags & TF_DISCONNECTED) { /* socket closed by the kernel before hw told us it connected */ diff --git a/sys/dev/cxgbe/tom/t4_cpl_io.c b/sys/dev/cxgbe/tom/t4_cpl_io.c index 5c39ae5fa8f3..6e34d5f54897 100644 --- a/sys/dev/cxgbe/tom/t4_cpl_io.c +++ b/sys/dev/cxgbe/tom/t4_cpl_io.c @@ -245,13 +245,13 @@ send_reset(struct adapter *sc, struct toepcb *toep, uint32_t snd_nxt) struct cpl_abort_req *req; int tid = toep->tid; struct inpcb *inp = toep->inp; - struct tcpcb *tp = intotcpcb(inp); /* don't use if INP_DROPPED */ + struct tcpcb *tp = intotcpcb(inp); INP_WLOCK_ASSERT(inp); CTR6(KTR_CXGBE, "%s: tid %d (%s), toep_flags 0x%x, inp_flags 0x%x%s", __func__, toep->tid, - inp->inp_flags & INP_DROPPED ? "inp dropped" : + tp->t_flags & TF_DISCONNECTED ? "TCP disconnected" : tcpstates[tp->t_state], toep->flags, inp->inp_flags, toep->flags & TPF_ABORT_SHUTDOWN ? @@ -273,7 +273,7 @@ send_reset(struct adapter *sc, struct toepcb *toep, uint32_t snd_nxt) req = wrtod(wr); INIT_TP_WR_MIT_CPL(req, CPL_ABORT_REQ, tid); - if (inp->inp_flags & INP_DROPPED) + if (tp->t_flags & TF_DISCONNECTED) req->rsvd0 = htobe32(snd_nxt); else req->rsvd0 = htobe32(tp->snd_nxt); @@ -284,7 +284,7 @@ send_reset(struct adapter *sc, struct toepcb *toep, uint32_t snd_nxt) * XXX: What's the correct way to tell that the inp hasn't been detached * from its socket? Should I even be flushing the snd buffer here? */ - if ((inp->inp_flags & INP_DROPPED) == 0) { + if ((tp->t_flags & TF_DISCONNECTED) == 0) { struct socket *so = inp->inp_socket; if (so != NULL) /* because I'm not sure. See comment above */ @@ -496,9 +496,6 @@ t4_close_conn(struct adapter *sc, struct toepcb *toep) #define MIN_ISO_TX_CREDITS (howmany(sizeof(struct cpl_tx_data_iso), 16)) #define MIN_TX_CREDITS(iso) \ (MIN_OFLD_TX_CREDITS + ((iso) ? MIN_ISO_TX_CREDITS : 0)) -#define MIN_OFLD_TX_V2_CREDITS (howmany(sizeof(struct fw_ofld_tx_data_v2_wr) + 1, 16)) -#define MIN_TX_V2_CREDITS(iso) \ - (MIN_OFLD_TX_V2_CREDITS + ((iso) ? MIN_ISO_TX_CREDITS : 0)) _Static_assert(MAX_OFLD_TX_CREDITS <= MAX_OFLD_TX_SDESC_CREDITS, "MAX_OFLD_TX_SDESC_CREDITS too small"); @@ -546,46 +543,6 @@ max_dsgl_nsegs(int tx_credits, int iso) return (nseg); } -/* Maximum amount of immediate data we could stuff in a WR */ -static inline int -max_imm_payload_v2(int tx_credits, int iso) -{ - const int iso_cpl_size = iso ? sizeof(struct cpl_tx_data_iso) : 0; - - KASSERT(tx_credits >= 0 && - tx_credits <= MAX_OFLD_TX_CREDITS, - ("%s: %d credits", __func__, tx_credits)); - - if (tx_credits < MIN_TX_V2_CREDITS(iso)) - return (0); - - return (tx_credits * 16 - sizeof(struct fw_ofld_tx_data_v2_wr) - - iso_cpl_size); -} - -/* Maximum number of SGL entries we could stuff in a WR */ -static inline int -max_dsgl_nsegs_v2(int tx_credits, int iso, int imm_payload) -{ - int nseg = 1; /* ulptx_sgl has room for 1, rest ulp_tx_sge_pair */ - int sge_pair_credits = tx_credits - MIN_TX_V2_CREDITS(iso); - - KASSERT(tx_credits >= 0 && - tx_credits <= MAX_OFLD_TX_CREDITS, - ("%s: %d credits", __func__, tx_credits)); - - if (tx_credits < MIN_TX_V2_CREDITS(iso) || - sge_pair_credits <= howmany(imm_payload, 16)) - return (0); - sge_pair_credits -= howmany(imm_payload, 16); - - nseg += 2 * (sge_pair_credits * 16 / 24); - if ((sge_pair_credits * 16) % 24 == 16) - nseg++; - - return (nseg); -} - static inline void write_tx_wr(void *dst, struct toepcb *toep, int fw_wr_opcode, unsigned int immdlen, unsigned int plen, uint8_t credits, int shove, @@ -613,35 +570,6 @@ write_tx_wr(void *dst, struct toepcb *toep, int fw_wr_opcode, } } -static inline void -write_tx_v2_wr(void *dst, struct toepcb *toep, int fw_wr_opcode, - unsigned int immdlen, unsigned int plen, uint8_t credits, int shove, - int ulp_submode) -{ - struct fw_ofld_tx_data_v2_wr *txwr = dst; - uint32_t flags; - - memset(txwr, 0, sizeof(*txwr)); - txwr->op_to_immdlen = htobe32(V_WR_OP(fw_wr_opcode) | - V_FW_WR_IMMDLEN(immdlen)); - txwr->flowid_len16 = htobe32(V_FW_WR_FLOWID(toep->tid) | - V_FW_WR_LEN16(credits)); - txwr->plen = htobe32(plen); - flags = V_TX_ULP_MODE(ULP_MODE_NVMET) | V_TX_ULP_SUBMODE(ulp_submode) | - V_TX_URG(0) | V_TX_SHOVE(shove); - - if (toep->params.tx_align > 0) { - if (plen < 2 * toep->params.emss) - flags |= F_FW_OFLD_TX_DATA_WR_LSODISABLE; - else - flags |= F_FW_OFLD_TX_DATA_WR_ALIGNPLD | - (toep->params.nagle == 0 ? 0 : - F_FW_OFLD_TX_DATA_WR_ALIGNPLDSHOVE); - } - - txwr->lsodisable_to_flags = htobe32(flags); -} - /* * Generate a DSGL from a starting mbuf. The total number of segments and the * maximum segments in any one mbuf are provided. @@ -1300,7 +1228,7 @@ write_nvme_mbuf_wr(struct toepcb *toep, struct mbuf *sndptr) { struct mbuf *m; const struct nvme_tcp_common_pdu_hdr *hdr; - struct fw_v2_nvmet_tx_data_wr *txwr; + struct fw_ofld_tx_data_wr *txwr; struct cpl_tx_data_iso *cpl_iso; void *p; struct wrqe *wr; @@ -1330,29 +1258,16 @@ write_nvme_mbuf_wr(struct toepcb *toep, struct mbuf *sndptr) return (wr); } - /* - * The first mbuf is the PDU header that is always sent as - * immediate data. - */ - imm_data = sndptr->m_len; - iso = mbuf_iscsi_iso(sndptr); - max_imm = max_imm_payload_v2(tx_credits, iso); - - /* - * Not enough credits for the PDU header. - */ - if (imm_data > max_imm) - return (NULL); - - max_nsegs = max_dsgl_nsegs_v2(tx_credits, iso, imm_data); + max_imm = max_imm_payload(tx_credits, iso); + max_nsegs = max_dsgl_nsegs(tx_credits, iso); iso_mss = mbuf_iscsi_iso_mss(sndptr); - plen = imm_data; + plen = 0; nsegs = 0; max_nsegs_1mbuf = 0; /* max # of SGL segments in any one mbuf */ nomap_mbuf_seen = false; - for (m = sndptr->m_next; m != NULL; m = m->m_next) { + for (m = sndptr; m != NULL; m = m->m_next) { int n; if (m->m_flags & M_EXTPG) @@ -1440,13 +1355,13 @@ write_nvme_mbuf_wr(struct toepcb *toep, struct mbuf *sndptr) if (iso) wr_len += sizeof(struct cpl_tx_data_iso); if (plen <= max_imm && !nomap_mbuf_seen) { - /* Immediate data tx for full PDU */ + /* Immediate data tx */ imm_data = plen; wr_len += plen; nsegs = 0; } else { /* DSGL tx for PDU data */ - wr_len += roundup2(imm_data, 16); + imm_data = 0; wr_len += sizeof(struct ulptx_sgl) + ((3 * (nsegs - 1)) / 2 + ((nsegs - 1) & 1)) * 8; } @@ -1460,7 +1375,7 @@ write_nvme_mbuf_wr(struct toepcb *toep, struct mbuf *sndptr) credits = howmany(wr->wr_len, 16); if (iso) { - write_tx_v2_wr(txwr, toep, FW_V2_NVMET_TX_DATA_WR, + write_tx_wr(txwr, toep, FW_ISCSI_TX_DATA_WR, imm_data + sizeof(struct cpl_tx_data_iso), adjusted_plen, credits, shove, ulp_submode | ULP_ISO); cpl_iso = (struct cpl_tx_data_iso *)(txwr + 1); @@ -1470,16 +1385,15 @@ write_nvme_mbuf_wr(struct toepcb *toep, struct mbuf *sndptr) hdr->pdo); p = cpl_iso + 1; } else { - write_tx_v2_wr(txwr, toep, FW_V2_NVMET_TX_DATA_WR, imm_data, + write_tx_wr(txwr, toep, FW_OFLD_TX_DATA_WR, imm_data, adjusted_plen, credits, shove, ulp_submode); p = txwr + 1; } - /* PDU header (and immediate data payload). */ - m_copydata(sndptr, 0, imm_data, p); - if (nsegs != 0) { - p = roundup2((char *)p + imm_data, 16); - write_tx_sgl(p, sndptr->m_next, NULL, nsegs, max_nsegs_1mbuf); + if (imm_data != 0) { + m_copydata(sndptr, 0, plen, p); + } else { + write_tx_sgl(p, sndptr, NULL, nsegs, max_nsegs_1mbuf); if (wr_len & 0xf) { uint64_t *pad = (uint64_t *)((uintptr_t)txwr + wr_len); *pad = 0; @@ -1674,8 +1588,8 @@ t4_tod_output(struct toedev *tod, struct tcpcb *tp) struct toepcb *toep = tp->t_toe; INP_WLOCK_ASSERT(inp); - KASSERT((inp->inp_flags & INP_DROPPED) == 0, - ("%s: inp %p dropped.", __func__, inp)); + KASSERT((tp->t_flags & TF_DISCONNECTED) == 0, + ("%s: tcpcb %p disconnected", __func__, tp)); KASSERT(toep != NULL, ("%s: toep is NULL", __func__)); t4_push_data(sc, toep, 0); @@ -1693,8 +1607,8 @@ t4_send_fin(struct toedev *tod, struct tcpcb *tp) struct toepcb *toep = tp->t_toe; INP_WLOCK_ASSERT(inp); - KASSERT((inp->inp_flags & INP_DROPPED) == 0, - ("%s: inp %p dropped.", __func__, inp)); + KASSERT((tp->t_flags & TF_DISCONNECTED) == 0, + ("%s: tcpcb %p disconnected", __func__, tp)); KASSERT(toep != NULL, ("%s: toep is NULL", __func__)); toep->flags |= TPF_SEND_FIN; @@ -1714,8 +1628,8 @@ t4_send_rst(struct toedev *tod, struct tcpcb *tp) struct toepcb *toep = tp->t_toe; INP_WLOCK_ASSERT(inp); - KASSERT((inp->inp_flags & INP_DROPPED) == 0, - ("%s: inp %p dropped.", __func__, inp)); + KASSERT((tp->t_flags & TF_DISCONNECTED) == 0, + ("%s: tcpcb %p disconnected", __func__, tp)); KASSERT(toep != NULL, ("%s: toep is NULL", __func__)); /* hmmmm */ @@ -2007,7 +1921,7 @@ do_abort_req(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) } toep->flags |= TPF_ABORT_SHUTDOWN; - if ((inp->inp_flags & INP_DROPPED) == 0) { + if ((tp->t_flags & TF_DISCONNECTED) == 0) { struct socket *so = inp->inp_socket; if (so != NULL) @@ -2096,17 +2010,16 @@ do_rx_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) m_adj(m, sizeof(*cpl)); len = m->m_pkthdr.len; + tp = intotcpcb(inp); INP_WLOCK(inp); - if (inp->inp_flags & INP_DROPPED) { - CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), inp_flags 0x%x", - __func__, tid, len, inp->inp_flags); + if (tp->t_flags & TF_DISCONNECTED) { + CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), t_flags 0x%x", + __func__, tid, len, tp->t_flags); INP_WUNLOCK(inp); m_freem(m); return (0); } - tp = intotcpcb(inp); - if (__predict_false(ulp_mode(toep) == ULP_MODE_TLS && toep->flags & TPF_TLS_RECEIVE)) { /* Received "raw" data on a TLS socket. */ @@ -2256,6 +2169,7 @@ do_fw4_ack(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) } inp = toep->inp; + tp = intotcpcb(inp); KASSERT(opcode == CPL_FW4_ACK, ("%s: unexpected opcode 0x%x", __func__, opcode)); @@ -2269,10 +2183,8 @@ do_fw4_ack(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) return (0); } - KASSERT((inp->inp_flags & INP_DROPPED) == 0, - ("%s: inp_flags 0x%x", __func__, inp->inp_flags)); - - tp = intotcpcb(inp); + KASSERT((tp->t_flags & TF_DISCONNECTED) == 0, + ("%s: t_flags 0x%x", __func__, tp->t_flags)); if (cpl->flags & CPL_FW4_ACK_FLAGS_SEQVAL) { tcp_seq snd_una = be32toh(cpl->snd_una); @@ -2713,8 +2625,9 @@ sendanother: /* Inlined tcp_usr_send(). */ inp = toep->inp; + tp = intotcpcb(inp); INP_WLOCK(inp); - if (inp->inp_flags & INP_DROPPED) { + if (tp->t_flags & TF_DISCONNECTED) { INP_WUNLOCK(inp); SOCK_IO_SEND_UNLOCK(so); error = ECONNRESET; @@ -2728,8 +2641,7 @@ sendanother: sbappendstream(sb, m, 0); m = NULL; - if (!(inp->inp_flags & INP_DROPPED)) { - tp = intotcpcb(inp); + if (!(tp->t_flags & TF_DISCONNECTED)) { if (moretocome) tp->t_flags |= TF_MORETOCOME; error = tcp_output(tp); diff --git a/sys/dev/cxgbe/tom/t4_ddp.c b/sys/dev/cxgbe/tom/t4_ddp.c index 35fb1061d867..9d422c2b793e 100644 --- a/sys/dev/cxgbe/tom/t4_ddp.c +++ b/sys/dev/cxgbe/tom/t4_ddp.c @@ -641,8 +641,8 @@ handle_ddp_data_aio(struct toepcb *toep, __be32 ddp_report, __be32 rcv_nxt, uint32_t report = be32toh(ddp_report); unsigned int db_idx; struct inpcb *inp = toep->inp; + struct tcpcb *tp = intotcpcb(inp); struct ddp_buffer *db; - struct tcpcb *tp; struct socket *so; struct sockbuf *sb; struct kaiocb *job; @@ -664,13 +664,13 @@ handle_ddp_data_aio(struct toepcb *toep, __be32 ddp_report, __be32 rcv_nxt, db = &toep->ddp.db[db_idx]; job = db->job; - if (__predict_false(inp->inp_flags & INP_DROPPED)) { + if (__predict_false(tp->t_flags & TF_DISCONNECTED)) { /* * This can happen due to an administrative tcpdrop(8). * Just fail the request with ECONNRESET. */ - CTR5(KTR_CXGBE, "%s: tid %u, seq 0x%x, len %d, inp_flags 0x%x", - __func__, toep->tid, be32toh(rcv_nxt), len, inp->inp_flags); + CTR5(KTR_CXGBE, "%s: tid %u, seq 0x%x, len %d, t_flags 0x%x", + __func__, toep->tid, be32toh(rcv_nxt), len, tp->t_flags); if (aio_clear_cancel_function(job)) ddp_complete_one(job, ECONNRESET); goto completed; @@ -859,7 +859,7 @@ handle_ddp_data_rcvbuf(struct toepcb *toep, __be32 ddp_report, __be32 rcv_nxt, { uint32_t report = be32toh(ddp_report); struct inpcb *inp = toep->inp; - struct tcpcb *tp; + struct tcpcb *tp = intotcpcb(inp); struct socket *so; struct sockbuf *sb; struct ddp_buffer *db; @@ -881,20 +881,18 @@ handle_ddp_data_rcvbuf(struct toepcb *toep, __be32 ddp_report, __be32 rcv_nxt, toep->ddp.active_id, toep->tid)); db = &toep->ddp.db[db_idx]; - if (__predict_false(inp->inp_flags & INP_DROPPED)) { + if (__predict_false(tp->t_flags & TF_DISCONNECTED)) { /* * This can happen due to an administrative tcpdrop(8). * Just ignore the received data. */ - CTR5(KTR_CXGBE, "%s: tid %u, seq 0x%x, len %d, inp_flags 0x%x", - __func__, toep->tid, be32toh(rcv_nxt), len, inp->inp_flags); + CTR5(KTR_CXGBE, "%s: tid %u, seq 0x%x, len %d, t_flags 0x%x", + __func__, toep->tid, be32toh(rcv_nxt), len, tp->t_flags); if (invalidated) complete_ddp_buffer(toep, db, db_idx); goto out; } - tp = intotcpcb(inp); - /* * For RX_DDP_COMPLETE, len will be zero and rcv_nxt is the * sequence number of the next byte to receive. The length of diff --git a/sys/dev/cxgbe/tom/t4_listen.c b/sys/dev/cxgbe/tom/t4_listen.c index b879f6883f25..359267b7db90 100644 --- a/sys/dev/cxgbe/tom/t4_listen.c +++ b/sys/dev/cxgbe/tom/t4_listen.c @@ -886,6 +886,7 @@ do_pass_open_rpl(struct sge_iq *iq, const struct rss_header *rss, unsigned int status = cpl->status; struct listen_ctx *lctx = lookup_stid(sc, stid); struct inpcb *inp = lctx->inp; + struct tcpcb *tp = intotcpcb(inp); #ifdef INVARIANTS unsigned int opcode = G_CPL_OPCODE(be32toh(OPCODE_TID(cpl))); #endif @@ -911,13 +912,13 @@ do_pass_open_rpl(struct sge_iq *iq, const struct rss_header *rss, * If the inp has been dropped (listening socket closed) then * listen_stop must have run and taken the inp out of the hash. */ - if (inp->inp_flags & INP_DROPPED) { + if (tp->t_flags & TF_DISCONNECTED) { KASSERT(listen_hash_del(sc, inp) == NULL, ("%s: inp %p still in listen hash", __func__, inp)); } #endif - if (inp->inp_flags & INP_DROPPED && status != CPL_ERR_NONE) { + if (tp->t_flags & TF_DISCONNECTED && status != CPL_ERR_NONE) { if (release_lctx(sc, lctx) != NULL) INP_WUNLOCK(inp); return (status); @@ -928,7 +929,7 @@ do_pass_open_rpl(struct sge_iq *iq, const struct rss_header *rss, * it has started the hardware listener. Stop it; the lctx will be * released in do_close_server_rpl. */ - if (inp->inp_flags & INP_DROPPED) { + if (tp->t_flags & TF_DISCONNECTED) { destroy_server(sc, lctx); INP_WUNLOCK(inp); return (status); @@ -1336,6 +1337,7 @@ do_pass_accept_req(struct sge_iq *iq, const struct rss_header *rss, unsigned int tid = GET_TID(cpl); struct listen_ctx *lctx = lookup_stid(sc, stid); struct inpcb *inp; + struct tcpcb *tp; struct socket *so; struct in_conninfo inc; struct tcphdr th; @@ -1477,10 +1479,11 @@ found: } inp = lctx->inp; /* listening socket, not owned by TOE */ + tp = intotcpcb(inp); INP_RLOCK(inp); /* Don't offload if the listening socket has closed */ - if (__predict_false(inp->inp_flags & INP_DROPPED)) { + if (__predict_false(tp->t_flags & TF_DISCONNECTED)) { INP_RUNLOCK(inp); NET_EPOCH_EXIT(et); REJECT_PASS_ACCEPT_REQ(false); @@ -1622,6 +1625,7 @@ do_pass_establish(struct sge_iq *iq, const struct rss_header *rss, struct synq_entry *synqe = lookup_tid(sc, tid); struct listen_ctx *lctx = synqe->lctx; struct inpcb *inp = lctx->inp, *new_inp; + struct tcpcb *tp = intotcpcb(inp); struct socket *so; struct tcphdr th; struct tcpopt to; @@ -1653,7 +1657,7 @@ do_pass_establish(struct sge_iq *iq, const struct rss_header *rss, KASSERT(vi->adapter == sc, ("%s: vi %p, sc %p mismatch", __func__, vi, sc)); - if (__predict_false(inp->inp_flags & INP_DROPPED)) { + if (__predict_false(tp->t_flags & TF_DISCONNECTED)) { reset: send_abort_rpl_synqe(TOEDEV(ifp), synqe, CPL_ABORT_SEND_RST); INP_WUNLOCK(inp); diff --git a/sys/dev/cxgbe/tom/t4_tls.c b/sys/dev/cxgbe/tom/t4_tls.c index bbcc1c88c3db..0616279ba15e 100644 --- a/sys/dev/cxgbe/tom/t4_tls.c +++ b/sys/dev/cxgbe/tom/t4_tls.c @@ -762,7 +762,7 @@ do_tls_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) unsigned int tid = GET_TID(cpl); struct toepcb *toep = lookup_tid(sc, tid); struct inpcb *inp = toep->inp; - struct tcpcb *tp; + struct tcpcb *tp = intotcpcb(inp); int len; /* XXX: Should this match do_rx_data instead? */ @@ -781,9 +781,9 @@ do_tls_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) ("%s: payload length mismatch", __func__)); INP_WLOCK(inp); - if (inp->inp_flags & INP_DROPPED) { - CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), inp_flags 0x%x", - __func__, tid, len, inp->inp_flags); + if (tp->t_flags & TF_DISCONNECTED) { + CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), t_flags 0x%x", + __func__, tid, len, tp->t_flags); INP_WUNLOCK(inp); m_freem(m); return (0); @@ -803,7 +803,6 @@ do_tls_data(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) #endif } - tp = intotcpcb(inp); tp->t_rcvtime = ticks; #ifdef VERBOSE_TRACES @@ -824,7 +823,7 @@ do_rx_tls_cmp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) unsigned int tid = GET_TID(cpl); struct toepcb *toep = lookup_tid(sc, tid); struct inpcb *inp = toep->inp; - struct tcpcb *tp; + struct tcpcb *tp = intotcpcb(inp); struct socket *so; struct sockbuf *sb; struct mbuf *tls_data; @@ -851,9 +850,9 @@ do_rx_tls_cmp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) ("%s: payload length mismatch", __func__)); INP_WLOCK(inp); - if (inp->inp_flags & INP_DROPPED) { - CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), inp_flags 0x%x", - __func__, tid, len, inp->inp_flags); + if (tp->t_flags & TF_DISCONNECTED) { + CTR4(KTR_CXGBE, "%s: tid %u, rx (%d bytes), t_flags 0x%x", + __func__, tid, len, tp->t_flags); INP_WUNLOCK(inp); m_freem(m); return (0); @@ -862,7 +861,6 @@ do_rx_tls_cmp(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) pdu_length = G_CPL_RX_TLS_CMP_PDULENGTH(be32toh(cpl->pdulength_length)); so = inp_inpcbtosocket(inp); - tp = intotcpcb(inp); #ifdef VERBOSE_TRACES CTR6(KTR_CXGBE, "%s: tid %u PDU len %d len %d seq %u, rcv_nxt %u", diff --git a/sys/dev/cxgbe/tom/t4_tom.c b/sys/dev/cxgbe/tom/t4_tom.c index 8dfffd465345..950608053be7 100644 --- a/sys/dev/cxgbe/tom/t4_tom.c +++ b/sys/dev/cxgbe/tom/t4_tom.c @@ -1830,7 +1830,7 @@ live_tid_failure_cleanup(struct adapter *sc, struct toepcb *toep, u_int status) INP_WLOCK(inp); tp = intotcpcb(inp); toep->flags |= TPF_ABORT_SHUTDOWN; - if ((inp->inp_flags & INP_DROPPED) == 0) { + if ((tp->t_flags & TF_DISCONNECTED) == 0) { struct socket *so = inp->inp_socket; if (so != NULL) @@ -2283,8 +2283,8 @@ find_offload_adapter_cb(struct adapter *sc, void *arg) struct find_offload_adapter_data *fa = arg; struct socket *so = fa->so; struct tom_data *td = sc->tom_softc; - struct tcpcb *tp; - struct inpcb *inp; + struct inpcb *inp = sotoinpcb(so); + struct tcpcb *tp = intotcpcb(inp); /* Non-TCP were filtered out earlier. */ MPASS(so->so_proto->pr_protocol == IPPROTO_TCP); @@ -2295,10 +2295,8 @@ find_offload_adapter_cb(struct adapter *sc, void *arg) if (td == NULL) return; /* TOE not enabled on this adapter. */ - inp = sotoinpcb(so); INP_WLOCK(inp); - if ((inp->inp_flags & INP_DROPPED) == 0) { - tp = intotcpcb(inp); + if ((tp->t_flags & TF_DISCONNECTED) == 0) { if (tp->t_flags & TF_TOE && tp->tod == &td->tod) fa->sc = sc; /* Found. */ } diff --git a/sys/dev/dcons/dcons_crom.c b/sys/dev/dcons/dcons_crom.c index d31a69adf03c..59e30935d04b 100644 --- a/sys/dev/dcons/dcons_crom.c +++ b/sys/dev/dcons/dcons_crom.c @@ -253,7 +253,7 @@ static device_method_t dcons_crom_methods[] = { DEVMETHOD(device_probe, dcons_crom_probe), DEVMETHOD(device_attach, dcons_crom_attach), DEVMETHOD(device_detach, dcons_crom_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t dcons_crom_driver = { diff --git a/sys/dev/dpaa/bman_fdt.c b/sys/dev/dpaa/bman_fdt.c index dffec52d5248..330db7b89715 100644 --- a/sys/dev/dpaa/bman_fdt.c +++ b/sys/dev/dpaa/bman_fdt.c @@ -56,7 +56,7 @@ static device_method_t bman_methods[] = { DEVMETHOD(device_resume, bman_resume), DEVMETHOD(device_shutdown, bman_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t bman_driver = { @@ -93,7 +93,7 @@ static device_method_t bm_portals_methods[] = { DEVMETHOD(device_attach, bman_portals_fdt_attach), DEVMETHOD(device_detach, bman_portals_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t bm_portals_driver = { @@ -136,25 +136,6 @@ bman_portals_fdt_probe(device_t dev) return (BUS_PROBE_DEFAULT); } -static phandle_t -bman_portal_find_cpu(int cpu) -{ - phandle_t node; - pcell_t reg; - - node = OF_finddevice("/cpus"); - if (node == -1) - return (node); - - for (node = OF_child(node); node != 0; node = OF_peer(node)) { - if (OF_getprop(node, "reg", ®, sizeof(reg)) <= 0) - continue; - if (reg == cpu) - return (node); - } - return (-1); -} - static int bman_portals_fdt_attach(device_t dev) { @@ -185,17 +166,15 @@ bman_portals_fdt_attach(device_t dev) } /* Checkout related cpu */ if (OF_getprop(child, "cpu-handle", (void *)&cpu, - sizeof(cpu)) <= 0) { - cpu = bman_portal_find_cpu(cpus); - if (cpu <= 0) - continue; - } - /* Acquire cpu number */ - cpu_node = OF_instance_to_package(cpu); - if (OF_getencprop(cpu_node, "reg", &cpu_num, sizeof(cpu_num)) <= 0) { - device_printf(dev, "Could not retrieve CPU number.\n"); - return (ENXIO); - } + sizeof(cpu)) > 0) { + cpu_node = OF_instance_to_package(cpu); + /* Acquire cpu number */ + if (OF_getencprop(cpu_node, "reg", &cpu_num, sizeof(cpu_num)) <= 0) { + device_printf(dev, "Could not retrieve CPU number.\n"); + return (ENXIO); + } + } else + cpu_num = cpus; cpus++; diff --git a/sys/dev/dpaa/fman_fdt.c b/sys/dev/dpaa/fman_fdt.c index 2386f4e7ec0b..4d3723b6de4d 100644 --- a/sys/dev/dpaa/fman_fdt.c +++ b/sys/dev/dpaa/fman_fdt.c @@ -56,7 +56,7 @@ static device_method_t fman_methods[] = { DEVMETHOD(bus_alloc_resource, fman_alloc_resource), DEVMETHOD(bus_activate_resource, fman_activate_resource), DEVMETHOD(bus_release_resource, fman_release_resource), - { 0, 0 } + DEVMETHOD_END }; DEFINE_CLASS_1(fman, fman_driver, fman_methods, diff --git a/sys/dev/dpaa/fman_mdio.c b/sys/dev/dpaa/fman_mdio.c index 6ca12befe9e7..8df716fc5571 100644 --- a/sys/dev/dpaa/fman_mdio.c +++ b/sys/dev/dpaa/fman_mdio.c @@ -90,7 +90,7 @@ static device_method_t pqmdio_methods[] = { DEVMETHOD(miibus_readreg, pqmdio_miibus_readreg), DEVMETHOD(miibus_writereg, pqmdio_miibus_writereg), - { 0, 0 } + DEVMETHOD_END }; static struct ofw_compat_data mdio_compat_data[] = { diff --git a/sys/dev/dpaa/if_dtsec_fdt.c b/sys/dev/dpaa/if_dtsec_fdt.c index b37f32c07b99..441ff9c96c50 100644 --- a/sys/dev/dpaa/if_dtsec_fdt.c +++ b/sys/dev/dpaa/if_dtsec_fdt.c @@ -77,7 +77,7 @@ static device_method_t dtsec_methods[] = { DEVMETHOD(miibus_writereg, dtsec_miibus_writereg), DEVMETHOD(miibus_statchg, dtsec_miibus_statchg), - { 0, 0 } + DEVMETHOD_END }; static driver_t dtsec_driver = { diff --git a/sys/dev/dpaa/qman_fdt.c b/sys/dev/dpaa/qman_fdt.c index 3f22ea4d651a..89bf802e0067 100644 --- a/sys/dev/dpaa/qman_fdt.c +++ b/sys/dev/dpaa/qman_fdt.c @@ -56,7 +56,7 @@ static device_method_t qman_methods[] = { DEVMETHOD(device_resume, qman_resume), DEVMETHOD(device_shutdown, qman_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t qman_driver = { @@ -93,7 +93,7 @@ static device_method_t qm_portals_methods[] = { DEVMETHOD(device_attach, qman_portals_fdt_attach), DEVMETHOD(device_detach, qman_portals_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t qm_portals_driver = { @@ -136,25 +136,6 @@ qman_portals_fdt_probe(device_t dev) return (BUS_PROBE_DEFAULT); } -static phandle_t -qman_portal_find_cpu(int cpu) -{ - phandle_t node; - pcell_t reg; - - node = OF_finddevice("/cpus"); - if (node == -1) - return (-1); - - for (node = OF_child(node); node != 0; node = OF_peer(node)) { - if (OF_getprop(node, "reg", ®, sizeof(reg)) <= 0) - continue; - if (reg == cpu) - return (node); - } - return (-1); -} - static int qman_portals_fdt_attach(device_t dev) { @@ -213,18 +194,15 @@ qman_portals_fdt_attach(device_t dev) } /* Checkout related cpu */ if (OF_getprop(child, "cpu-handle", (void *)&cpu, - sizeof(cpu)) <= 0) { - cpu = qman_portal_find_cpu(cpus); - if (cpu <= 0) - continue; - } - /* Acquire cpu number */ - cpu_node = OF_instance_to_package(cpu); - if (OF_getencprop(cpu_node, "reg", &cpu_num, sizeof(cpu_num)) <= 0) { - device_printf(dev, "Could not retrieve CPU number.\n"); - return (ENXIO); - } - + sizeof(cpu)) > 0) { + cpu_node = OF_instance_to_package(cpu); + /* Acquire cpu number */ + if (OF_getencprop(cpu_node, "reg", &cpu_num, sizeof(cpu_num)) <= 0) { + device_printf(dev, "Could not retrieve CPU number.\n"); + return (ENXIO); + } + } else + cpu_num = cpus; cpus++; if (ofw_bus_gen_setup_devinfo(&ofw_di, child) != 0) { diff --git a/sys/dev/dpaa2/dpaa2_buf.c b/sys/dev/dpaa2/dpaa2_buf.c index 7739eda5d8de..228e4448210d 100644 --- a/sys/dev/dpaa2/dpaa2_buf.c +++ b/sys/dev/dpaa2/dpaa2_buf.c @@ -42,6 +42,7 @@ #include "dpaa2_swp.h" #include "dpaa2_swp_if.h" #include "dpaa2_ni.h" +#include "dpaa2_frame.h" MALLOC_DEFINE(M_DPAA2_RXB, "dpaa2_rxb", "DPAA2 DMA-mapped buffer (Rx)"); @@ -129,7 +130,7 @@ dpaa2_buf_seed_rxb(device_t dev, struct dpaa2_buf *buf, int size, struct mtx *dma_mtx) { struct dpaa2_ni_softc *sc = device_get_softc(dev); - struct dpaa2_fa *fa; + struct dpaa2_swa *swa; bool map_created = false; bool mbuf_alloc = false; int error; @@ -154,7 +155,8 @@ dpaa2_buf_seed_rxb(device_t dev, struct dpaa2_buf *buf, int size, if (__predict_true(buf->m == NULL)) { buf->m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, size); if (__predict_false(buf->m == NULL)) { - device_printf(dev, "%s: m_getjcl() failed\n", __func__); + device_printf(dev, "%s: m_getjcl(%d) failed\n", + __func__, size); error = ENOMEM; goto fail_mbuf_alloc; } @@ -178,9 +180,9 @@ dpaa2_buf_seed_rxb(device_t dev, struct dpaa2_buf *buf, int size, buf->vaddr = buf->m->m_data; /* Populate frame annotation for future use */ - fa = (struct dpaa2_fa *)buf->vaddr; - fa->magic = DPAA2_MAGIC; - fa->buf = buf; + swa = (struct dpaa2_swa *)buf->vaddr; + swa->magic = DPAA2_MAGIC; + swa->buf = buf; bus_dmamap_sync(buf->dmat, buf->dmap, BUS_DMASYNC_PREREAD); diff --git a/sys/dev/dpaa2/dpaa2_buf.h b/sys/dev/dpaa2/dpaa2_buf.h index 853a4fa78d3a..16ea7e1905ac 100644 --- a/sys/dev/dpaa2/dpaa2_buf.h +++ b/sys/dev/dpaa2/dpaa2_buf.h @@ -33,6 +33,8 @@ #include <sys/malloc.h> #include <sys/lock.h> #include <sys/mutex.h> +#include <sys/systm.h> +#include <sys/mbuf.h> #include <machine/bus.h> diff --git a/sys/dev/dpaa2/dpaa2_frame.c b/sys/dev/dpaa2/dpaa2_frame.c new file mode 100644 index 000000000000..005708228058 --- /dev/null +++ b/sys/dev/dpaa2/dpaa2_frame.c @@ -0,0 +1,241 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Dmitry Salychev + * Copyright (c) 2026 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> + +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/endian.h> + +#include <vm/vm.h> +#include <vm/pmap.h> + +#include <machine/vmparam.h> + +#include "dpaa2_types.h" +#include "dpaa2_frame.h" +#include "dpaa2_buf.h" +#include "dpaa2_swp.h" + +/** + * @brief Build a DPAA2 frame descriptor. + */ +int +dpaa2_fd_build(device_t dev, const uint16_t tx_data_off, struct dpaa2_buf *buf, + bus_dma_segment_t *segs, const int nsegs, struct dpaa2_fd *fd) +{ + struct dpaa2_buf *sgt = buf->sgt; + struct dpaa2_sg_entry *sge; + struct dpaa2_swa *swa; + int i, error; + + if (buf == NULL || segs == NULL || nsegs == 0 || fd == NULL) + return (EINVAL); + + KASSERT(nsegs <= DPAA2_TX_SEGLIMIT, ("%s: too many segments", __func__)); + KASSERT(buf->opt != NULL, ("%s: no Tx ring?", __func__)); + KASSERT(sgt != NULL, ("%s: no S/G table?", __func__)); + KASSERT(sgt->vaddr != NULL, ("%s: no S/G vaddr?", __func__)); + + memset(fd, 0, sizeof(*fd)); + + /* Populate and map S/G table */ + if (__predict_true(nsegs <= DPAA2_TX_SEGLIMIT)) { + sge = (struct dpaa2_sg_entry *)sgt->vaddr + tx_data_off; + for (i = 0; i < nsegs; i++) { + sge[i].addr = (uint64_t)segs[i].ds_addr; + sge[i].len = (uint32_t)segs[i].ds_len; + sge[i].offset_fmt = 0u; + } + sge[i-1].offset_fmt |= 0x8000u; /* set final entry flag */ + + KASSERT(sgt->paddr == 0, ("%s: paddr(%#jx) != 0", __func__, + sgt->paddr)); + + error = bus_dmamap_load(sgt->dmat, sgt->dmap, sgt->vaddr, + DPAA2_TX_SGT_SZ, dpaa2_dmamap_oneseg_cb, &sgt->paddr, + BUS_DMA_NOWAIT); + if (__predict_false(error != 0)) { + device_printf(dev, "%s: bus_dmamap_load() failed: " + "error=%d\n", __func__, error); + return (error); + } + + buf->paddr = sgt->paddr; + buf->vaddr = sgt->vaddr; + } else { + return (EINVAL); + } + + swa = (struct dpaa2_swa *)sgt->vaddr; + swa->magic = DPAA2_MAGIC; + swa->buf = buf; + + fd->addr = buf->paddr; + fd->data_length = (uint32_t)buf->m->m_pkthdr.len; + fd->bpid_ivp_bmt = 0; + fd->offset_fmt_sl = 0x2000u | tx_data_off; + fd->ctrl = (0x4u & DPAA2_FD_PTAC_MASK) << DPAA2_FD_PTAC_SHIFT; + + return (0); +} + +int +dpaa2_fd_err(struct dpaa2_fd *fd) +{ + return ((fd->ctrl >> DPAA2_FD_ERR_SHIFT) & DPAA2_FD_ERR_MASK); +} + +uint32_t +dpaa2_fd_data_len(struct dpaa2_fd *fd) +{ + if (dpaa2_fd_short_len(fd)) { + return (fd->data_length & DPAA2_FD_LEN_MASK); + } + return (fd->data_length); +} + +int +dpaa2_fd_format(struct dpaa2_fd *fd) +{ + return ((enum dpaa2_fd_format)((fd->offset_fmt_sl >> + DPAA2_FD_FMT_SHIFT) & DPAA2_FD_FMT_MASK)); +} + +bool +dpaa2_fd_short_len(struct dpaa2_fd *fd) +{ + return (((fd->offset_fmt_sl >> DPAA2_FD_SL_SHIFT) + & DPAA2_FD_SL_MASK) == 1); +} + +int +dpaa2_fd_offset(struct dpaa2_fd *fd) +{ + return (fd->offset_fmt_sl & DPAA2_FD_OFFSET_MASK); +} + +uint32_t +dpaa2_fd_get_frc(struct dpaa2_fd *fd) +{ + /* TODO: Convert endiannes in the other functions as well. */ + return (le32toh(fd->frame_ctx)); +} + +#ifdef _not_yet_ +void +dpaa2_fd_set_frc(struct dpaa2_fd *fd, uint32_t frc) +{ + /* TODO: Convert endiannes in the other functions as well. */ + fd->frame_ctx = htole32(frc); +} +#endif + +int +dpaa2_fa_get_swa(struct dpaa2_fd *fd, struct dpaa2_swa **swa) +{ + if (__predict_false(fd == NULL || swa == NULL)) + return (EINVAL); + + if (((fd->ctrl >> DPAA2_FD_PTAC_SHIFT) & DPAA2_FD_PTAC_PTA_MASK) == 0u) { + *swa = NULL; + return (ENOENT); + } + + *swa = (struct dpaa2_swa *)PHYS_TO_DMAP((bus_addr_t)fd->addr); + + return (0); +} + +int +dpaa2_fa_get_hwa(struct dpaa2_fd *fd, struct dpaa2_hwa **hwa) +{ + uint8_t *buf; + uint32_t hwo; /* HW annotation offset */ + + if (__predict_false(fd == NULL || hwa == NULL)) + return (EINVAL); + + /* + * As soon as the ASAL is in the 64-byte units, we don't need to + * calculate the exact length, but make sure that it isn't 0. + */ + if (((fd->ctrl >> DPAA2_FD_ASAL_SHIFT) & DPAA2_FD_ASAL_MASK) == 0u) { + *hwa = NULL; + return (ENOENT); + } + + buf = (uint8_t *)PHYS_TO_DMAP((bus_addr_t)fd->addr); + hwo = ((fd->ctrl >> DPAA2_FD_PTAC_SHIFT) & DPAA2_FD_PTAC_PTA_MASK) > 0u + ? DPAA2_FA_SWA_SIZE : 0u; + *hwa = (struct dpaa2_hwa *)(buf + hwo); + + return (0); +} + +int +dpaa2_fa_get_fas(struct dpaa2_fd *fd, struct dpaa2_hwa_fas *fas) +{ + struct dpaa2_hwa *hwa; + struct dpaa2_hwa_fas *fasp; + int rc; + + if (__predict_false(fd == NULL || fas == NULL)) + return (EINVAL); + + rc = dpaa2_fa_get_hwa(fd, &hwa); + if (__predict_false(rc != 0)) + return (rc); + + fasp = (struct dpaa2_hwa_fas *)&hwa->fas; + *fas = *fasp; + + return (rc); +} + +#ifdef _not_yet_ +int +dpaa2_fa_set_fas(struct dpaa2_fd *fd, struct dpaa2_hwa_fas *fas) +{ + struct dpaa2_hwa *hwa; + uint64_t *valp; + int rc; + + if (__predict_false(fd == NULL || fas == NULL)) + return (EINVAL); + + rc = dpaa2_fa_get_hwa(fd, &hwa); + if (__predict_false(rc != 0)) + return (rc); + + valp = (uint64_t *)fas; + hwa->fas = *valp; + + return (rc); +} +#endif diff --git a/sys/dev/dpaa2/dpaa2_frame.h b/sys/dev/dpaa2/dpaa2_frame.h new file mode 100644 index 000000000000..ab83b402efa4 --- /dev/null +++ b/sys/dev/dpaa2/dpaa2_frame.h @@ -0,0 +1,233 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Dmitry Salychev + * Copyright (c) 2026 Bjoern A. Zeeb + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _DPAA2_FRAME_H +#define _DPAA2_FRAME_H + +#include <sys/types.h> +#include <sys/bus.h> +#include <sys/kassert.h> + +#include "dpaa2_types.h" +#include "dpaa2_buf.h" + +/* + * Helper routines for the DPAA2 frames (e.g. descriptors, software/hardware + * annotations, etc.). + */ + +/* + * DPAA2 frame descriptor size, field offsets and masks. + * + * See 3.1.1 Frame descriptor format, + * 4.2.1.2.2 Structure of Frame Descriptors (FDs), + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +#define DPAA2_FD_SIZE 32u +#define DPAA2_FD_FMT_MASK (0x3u) +#define DPAA2_FD_FMT_SHIFT (12) +#define DPAA2_FD_ERR_MASK (0xFFu) +#define DPAA2_FD_ERR_SHIFT (0) +#define DPAA2_FD_SL_MASK (0x1u) +#define DPAA2_FD_SL_SHIFT (14) +#define DPAA2_FD_LEN_MASK (0x3FFFFu) +#define DPAA2_FD_OFFSET_MASK (0x0FFFu) +#define DPAA2_FD_PTAC_PTV2_MASK (0x1u) +#define DPAA2_FD_PTAC_PTV1_MASK (0x2u) +#define DPAA2_FD_PTAC_PTA_MASK (0x4u) +#define DPAA2_FD_PTAC_MASK (0x7u) +#define DPAA2_FD_PTAC_SHIFT (21) +#define DPAA2_FD_ASAL_MASK (0xFu) +#define DPAA2_FD_ASAL_SHIFT (16) + +/* + * DPAA2 frame annotation sizes + * + * NOTE: Accelerator-specific (HWA) annotation length is described in the 64-byte + * units by the FD[ASAL] bits and can be as big as 960 bytes. Current + * values describe what is actually supported by the DPAA2 drivers. + * + * See 3.1.1 Frame descriptor format, + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0 + */ +#define DPAA2_FA_SIZE 192u /* DPAA2 frame annotation */ +#define DPAA2_FA_SWA_SIZE 64u /* SW frame annotation */ +#define DPAA2_FA_HWA_SIZE 128u /* HW frame annotation */ +#define DPAA2_FA_WRIOP_SIZE 128u /* WRIOP HW annotation */ +#define DPAA2_FA_HWA_FAS_SIZE 8u /* Frame annotation status */ + +/* + * DPAA2 annotation valid bits in FD[FRC]. + * + * See 7.31.2 WRIOP FD frame context (FRC), + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +#define DPAA2_FD_FRC_FASV (1 << 15) +#define DPAA2_FD_FRC_FAEADV (1 << 14) +#define DPAA2_FD_FRC_FAPRV (1 << 13) +#define DPAA2_FD_FRC_FAIADV (1 << 12) +#define DPAA2_FD_FRC_FASWOV (1 << 11) +#define DPAA2_FD_FRC_FAICFDV (1 << 10) + +/* + * DPAA2 Frame annotation status word. + * + * See 7.34.3 Frame annotation status word (FAS), + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +#define DPAA2_FAS_L3CV (1 << 3) /* L3 csum validated */ +#define DPAA2_FAS_L3CE (1 << 2) /* L3 csum error */ +#define DPAA2_FAS_L4CV (1 << 1) /* L4 csum validated*/ +#define DPAA2_FAS_L4CE (1 << 0) /* L4 csum error */ + +/** + * @brief DPAA2 frame descriptor. + * + * addr: Memory address of the start of the buffer holding the + * frame data or the buffer containing the scatter/gather + * list. + * data_length: Length of the frame data (in bytes). + * bpid_ivp_bmt: Buffer pool ID (14 bit + BMT bit + IVP bit) + * offset_fmt_sl: Frame data offset, frame format and short-length fields. + * frame_ctx: Frame context. This field allows the sender of a frame + * to communicate some out-of-band information to the + * receiver of the frame. + * ctrl: Control bits (ERR, CBMT, ASAL, PTAC, DROPP, SC, DD). + * flow_ctx: Frame flow context. Associates the frame with a flow + * structure. QMan may use the FLC field for 3 purposes: + * stashing control, order definition point identification, + * and enqueue replication control. + * + * See 3.1.1 Frame descriptor format, + * 4.2.1.2.2 Structure of Frame Descriptors (FDs), + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +struct dpaa2_fd { + uint64_t addr; + uint32_t data_length; + uint16_t bpid_ivp_bmt; + uint16_t offset_fmt_sl; + uint32_t frame_ctx; + uint32_t ctrl; + uint64_t flow_ctx; +} __packed; +CTASSERT(sizeof(struct dpaa2_fd) == DPAA2_FD_SIZE); + +/** + * @brief WRIOP hardware frame annotation. + * + * See 7.34.2 WRIOP hardware frame annotation (FA), + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +struct dpaa2_hwa_wriop { + union { + struct { + uint64_t fas; + uint64_t timestamp; + /* XXX-DSL: more to add here... */ + } __packed; + uint8_t raw[128]; + }; +} __packed; +CTASSERT(sizeof(struct dpaa2_hwa_wriop) == DPAA2_FA_WRIOP_SIZE); + +/** + * @brief DPAA2 hardware frame annotation. + * + * See 3.4.1.2 Accelerator-specific annotation, + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +struct dpaa2_hwa { + union { + /* Keep fields common to all accelerators at the top. */ + struct { + uint64_t fas; + } __packed; + /* Keep accelerator-specific annotations below. */ + struct dpaa2_hwa_wriop wriop; + }; +} __packed; +CTASSERT(sizeof(struct dpaa2_hwa) == DPAA2_FA_HWA_SIZE); + +/** + * @brief DPAA2 software frame annotation (pass-through annotation). + * + * See 3.4.1.1 Pass-through annotation, + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +struct dpaa2_swa { + union { + struct { + uint32_t magic; + struct dpaa2_buf *buf; + }; + struct { + uint8_t pta1[32]; + uint8_t pta2[32]; + }; + uint8_t raw[64]; + }; +} __packed; +CTASSERT(sizeof(struct dpaa2_swa) == DPAA2_FA_SWA_SIZE); + +/** + * @brief Frame annotation status word. + * + * See 7.34.3 Frame annotation status word (FAS), + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, 06/2020 + */ +struct dpaa2_hwa_fas { + uint8_t _reserved1; + uint8_t ppid; + uint16_t ifpid; + uint32_t status; +} __packed; +CTASSERT(sizeof(struct dpaa2_hwa_fas) == DPAA2_FA_HWA_FAS_SIZE); + +int dpaa2_fd_build(device_t, const uint16_t, struct dpaa2_buf *, + bus_dma_segment_t *, const int, struct dpaa2_fd *); + +int dpaa2_fd_err(struct dpaa2_fd *); +uint32_t dpaa2_fd_data_len(struct dpaa2_fd *); +int dpaa2_fd_format(struct dpaa2_fd *); +bool dpaa2_fd_short_len(struct dpaa2_fd *); +int dpaa2_fd_offset(struct dpaa2_fd *); + +uint32_t dpaa2_fd_get_frc(struct dpaa2_fd *); +#ifdef _not_yet_ +void dpaa2_fd_set_frc(struct dpaa2_fd *, uint32_t); +#endif + +int dpaa2_fa_get_swa(struct dpaa2_fd *, struct dpaa2_swa **); +int dpaa2_fa_get_hwa(struct dpaa2_fd *, struct dpaa2_hwa **); +int dpaa2_fa_get_fas(struct dpaa2_fd *, struct dpaa2_hwa_fas *); +#ifdef _not_yet_ +int dpaa2_fa_set_fas(struct dpaa2_fd *, struct dpaa2_hwa_fas *); +#endif + +#endif /* _DPAA2_FRAME_H */ diff --git a/sys/dev/dpaa2/dpaa2_ni.c b/sys/dev/dpaa2/dpaa2_ni.c index 98a6c6047188..f85dc41a748c 100644 --- a/sys/dev/dpaa2/dpaa2_ni.c +++ b/sys/dev/dpaa2/dpaa2_ni.c @@ -1,8 +1,9 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright © 2021-2023 Dmitry Salychev - * Copyright © 2022 Mathew McBride + * Copyright (c) 2021-2026 Dmitry Salychev + * Copyright (c) 2022 Mathew McBride + * Copyright (c) 2026 Bjoern A. Zeeb * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -56,6 +57,7 @@ #include <sys/buf_ring.h> #include <sys/smp.h> #include <sys/proc.h> +#include <sys/sbuf.h> #include <vm/vm.h> #include <vm/pmap.h> @@ -96,6 +98,7 @@ #include "dpaa2_ni.h" #include "dpaa2_channel.h" #include "dpaa2_buf.h" +#include "dpaa2_frame.h" #define BIT(x) (1ul << (x)) #define WRIOP_VERSION(x, y, z) ((x) << 10 | (y) << 5 | (z) << 0) @@ -156,10 +159,6 @@ MALLOC_DEFINE(M_DPAA2_TXB, "dpaa2_txb", "DPAA2 DMA-mapped buffer (Tx)"); #define DPAA2_RX_BUFRING_SZ (4096u) #define DPAA2_RXE_BUFRING_SZ (1024u) #define DPAA2_TXC_BUFRING_SZ (4096u) -#define DPAA2_TX_SEGLIMIT (16u) /* arbitrary number */ -#define DPAA2_TX_SEG_SZ (PAGE_SIZE) -#define DPAA2_TX_SEGS_MAXSZ (DPAA2_TX_SEGLIMIT * DPAA2_TX_SEG_SZ) -#define DPAA2_TX_SGT_SZ (PAGE_SIZE) /* bytes */ /* Size of a buffer to keep a QoS table key configuration. */ #define ETH_QOS_KCFG_BUF_SIZE (PAGE_SIZE) @@ -186,15 +185,6 @@ MALLOC_DEFINE(M_DPAA2_TXB, "dpaa2_txb", "DPAA2 DMA-mapped buffer (Tx)"); #define DPAA2_NI_TXBUF_IDX_MASK (0xFFu) #define DPAA2_NI_TXBUF_IDX_SHIFT (49) -#define DPAA2_NI_FD_FMT_MASK (0x3u) -#define DPAA2_NI_FD_FMT_SHIFT (12) -#define DPAA2_NI_FD_ERR_MASK (0xFFu) -#define DPAA2_NI_FD_ERR_SHIFT (0) -#define DPAA2_NI_FD_SL_MASK (0x1u) -#define DPAA2_NI_FD_SL_SHIFT (14) -#define DPAA2_NI_FD_LEN_MASK (0x3FFFFu) -#define DPAA2_NI_FD_OFFSET_MASK (0x0FFFu) - /* Enables TCAM for Flow Steering and QoS look-ups. */ #define DPNI_OPT_HAS_KEY_MASKING 0x10 @@ -220,6 +210,9 @@ MALLOC_DEFINE(M_DPAA2_TXB, "dpaa2_txb", "DPAA2 DMA-mapped buffer (Tx)"); #define RXH_L4_B_2_3 (1 << 7) /* dst port in case of TCP/UDP/SCTP */ #define RXH_DISCARD (1 << 31) +/* Transmit checksum offload */ +#define DPAA2_CSUM_TX_OFFLOAD (CSUM_IP | CSUM_DELAY_DATA | CSUM_DELAY_DATA_IPV6) + /* Default Rx hash options, set during attaching. */ #define DPAA2_RXH_DEFAULT (RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3) @@ -369,19 +362,43 @@ static struct dpni_stat { int cnt; char *name; char *desc; -} dpni_stat_sysctls[DPAA2_NI_STAT_SYSCTLS] = { +} dpni_stat_sysctls[] = { /* PAGE, COUNTER, NAME, DESCRIPTION */ - { 0, 0, "in_all_frames", "All accepted ingress frames" }, - { 0, 1, "in_all_bytes", "Bytes in all accepted ingress frames" }, - { 0, 2, "in_multi_frames", "Multicast accepted ingress frames" }, - { 1, 0, "eg_all_frames", "All egress frames transmitted" }, - { 1, 1, "eg_all_bytes", "Bytes in all frames transmitted" }, - { 1, 2, "eg_multi_frames", "Multicast egress frames transmitted" }, - { 2, 0, "in_filtered_frames", "All ingress frames discarded due to " - "filtering" }, - { 2, 1, "in_discarded_frames", "All frames discarded due to errors" }, - { 2, 2, "in_nobuf_discards", "Discards on ingress side due to buffer " - "depletion in DPNI buffer pools" }, + { 0, 0, "in_all_frames", "All accepted ingress frames" }, + { 0, 1, "in_all_bytes", "Bytes in all accepted ingress frames" }, + { 0, 2, "in_mc_frames", "Multicast accepted ingress frames" }, + { 0, 3, "in_mc_bytes", "Bytes in received multicast frames" }, + { 0, 4, "in_bc_frames", "Broadcast accepted ingress frames" }, + { 0, 5, "in_bc_bytes", "Bytes in broadcast multicast frames" }, + + { 1, 0, "eg_all_frames", "All egress frames transmitted" }, + { 1, 1, "eg_all_bytes", "Bytes in all frames transmitted" }, + { 1, 2, "eg_mc_frames", "Multicast egress frames transmitted" }, + { 1, 3, "eg_mc_bytes", "Bytes in transmitted multicast frame" }, + { 1, 4, "eg_bc_frames", "Broadcast egress frames transmitted" }, + { 1, 5, "eg_bc_bytes", "Bytes in broadcast multicast frames" }, + + { 2, 0, "in_filtered_frames", "All ingress frames discarded due to filtering" }, + { 2, 1, "in_discarded_frames", "All frames discarded due to errors" }, + { 2, 2, "in_nobuf_discards", "Discards on ingress side due to buffer depletion in DPNI buffer pools" }, + { 2, 3, "eg_frames_disc", "Frames discarded on transmit due to DPNI configuration and/or frame state" }, + { 2, 4, "eg_frames_tx", "Frames that have been confirmed after transmission" }, + + /* XXX FIXME Page 3/4 can take a param as well not encoded here. */ + /* XXX 3/0 and 3/1 have the same description in the manual? Where's the difference? */ + { 3, 0, "bytes_dequeued", "Cumulative count of the number of bytes dequeued" }, + { 3, 1, "frames_dequeued", "Cumulative count of the number of frames dequeued" }, + { 3, 2, "bytes_enqueued_rej", "Cumulative count of the number of bytes in all frames whose enqueue was rejected." }, + { 3, 3, "frames_enqueued_rej", "Cumulative count of all frame enqueues rejected." }, + + { 4, 0, "fames_rej_tc", "Rejected frames in associated congestion point (valid if this TC has an associated congestion point)" }, + { 4, 1, "bytes_rej_tc", "Rejected bytes in associated congestion point (valid if this TC has an associated congestion point)" }, + + { 5, 0, "pol_red", "Policer RED packet counter. 32bit value valid only when policer is enabled." }, + { 5, 1, "pol_yel", "Policer YELLOW packet counter. 32bit value valid only when policer is enabled." }, + { 5, 2, "pol_gre", "Policer GREEN packet counter. 32bit value valid only when policer is enabled." }, + { 5, 3, "pol_re_red", "Policer recolored RED packet counter. 32bit value valid only when policer is enabled." }, + { 5, 4, "pol_re_yel", "Policer recolored YELLOW packet counter. 32bit value valid only when policer is enabled." }, }; struct dpaa2_ni_rx_ctx { @@ -421,18 +438,10 @@ static int dpaa2_ni_set_mac_addr(device_t); static int dpaa2_ni_set_hash(device_t, uint64_t); static int dpaa2_ni_set_dist_key(device_t, enum dpaa2_ni_dist_mode, uint64_t); -/* Frame descriptor routines */ -static int dpaa2_ni_build_fd(struct dpaa2_ni_softc *, struct dpaa2_ni_tx_ring *, - struct dpaa2_buf *, bus_dma_segment_t *, int, struct dpaa2_fd *); -static int dpaa2_ni_fd_err(struct dpaa2_fd *); -static uint32_t dpaa2_ni_fd_data_len(struct dpaa2_fd *); -static int dpaa2_ni_fd_format(struct dpaa2_fd *); -static bool dpaa2_ni_fd_short_len(struct dpaa2_fd *); -static int dpaa2_ni_fd_offset(struct dpaa2_fd *); - /* Various subroutines */ static int dpaa2_ni_cmp_api_version(struct dpaa2_ni_softc *, uint16_t, uint16_t); static int dpaa2_ni_prepare_key_cfg(struct dpkg_profile_cfg *, uint8_t *); +static int dpaa2_ni_update_csum_flags(struct dpaa2_fd *, struct mbuf *); /* Network interface routines */ static void dpaa2_ni_init(void *); @@ -472,6 +481,7 @@ static int dpaa2_ni_tx_conf(struct dpaa2_channel *, struct dpaa2_ni_fq *, static int dpaa2_ni_collect_stats(SYSCTL_HANDLER_ARGS); static int dpaa2_ni_collect_buf_num(SYSCTL_HANDLER_ARGS); static int dpaa2_ni_collect_buf_free(SYSCTL_HANDLER_ARGS); +static int dpaa2_ni_sysctl_link_state(SYSCTL_HANDLER_ARGS); static int dpaa2_ni_probe(device_t dev) @@ -512,6 +522,7 @@ dpaa2_ni_attach(device_t dev) sc->rx_sg_buf_frames = 0; sc->rx_enq_rej_frames = 0; sc->rx_ieoi_err_frames = 0; + sc->rx_other_err_frames = 0; sc->tx_single_buf_frames = 0; sc->tx_sg_frames = 0; @@ -559,6 +570,7 @@ dpaa2_ni_attach(device_t dev) if_settransmitfn(ifp, dpaa2_ni_transmit); if_setqflushfn(ifp, dpaa2_ni_qflush); + if_sethwassist(sc->ifp, DPAA2_CSUM_TX_OFFLOAD); if_setcapabilities(ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 | IFCAP_JUMBO_MTU); if_setcapenable(ifp, if_getcapabilities(ifp)); @@ -1738,7 +1750,7 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc) node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "stats", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "DPNI Statistics"); parent = SYSCTL_CHILDREN(node); - for (i = 0; i < DPAA2_NI_STAT_SYSCTLS; ++i) { + for (i = 0; i < nitems(dpni_stat_sysctls); ++i) { SYSCTL_ADD_PROC(ctx, parent, i, dpni_stat_sysctls[i].name, CTLTYPE_U64 | CTLFLAG_RD, sc, 0, dpaa2_ni_collect_stats, "IU", dpni_stat_sysctls[i].desc); @@ -1758,6 +1770,9 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc) SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "rx_ieoi_err_frames", CTLFLAG_RD, &sc->rx_ieoi_err_frames, "QMan IEOI error"); + SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "rx_other_err_frames", + CTLFLAG_RD, &sc->rx_other_err_frames, + "Other Rx frames with errors"); SYSCTL_ADD_UQUAD(ctx, parent, OID_AUTO, "tx_single_buf_frames", CTLFLAG_RD, &sc->tx_single_buf_frames, "Tx single buffer frames"); @@ -1772,9 +1787,8 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc) CTLTYPE_U32 | CTLFLAG_RD, sc, 0, dpaa2_ni_collect_buf_free, "IU", "number of free Rx buffers in the buffer pool"); - parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)); - /* Add channels statistics. */ + parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)); node = SYSCTL_ADD_NODE(ctx, parent, OID_AUTO, "channels", CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "DPNI Channels"); parent = SYSCTL_CHILDREN(node); @@ -1793,6 +1807,13 @@ dpaa2_ni_setup_sysctls(struct dpaa2_ni_softc *sc) "Tx dropped counter"); } + /* Add Link debugging options. */ + parent = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->dev)); + node = SYSCTL_ADD_PROC(ctx, parent, OID_AUTO, "link", + CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, + sc, 0, dpaa2_ni_sysctl_link_state, + "A", "DPNI link state information"); + return (0); } @@ -2528,6 +2549,7 @@ dpaa2_ni_transmit(if_t ifp, struct mbuf *m) ch = sc->channels[chidx]; error = buf_ring_enqueue(ch->xmit_br, m); if (__predict_false(error != 0)) { + if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1); m_freem(m); } else { taskqueue_enqueue(ch->cleanup_tq, &ch->cleanup_task); @@ -2598,25 +2620,11 @@ dpaa2_ni_ioctl(if_t ifp, u_long c, caddr_t data) break; case SIOCSIFCAP: changed = if_getcapenable(ifp) ^ ifr->ifr_reqcap; - if (changed & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) { - if ((ifr->ifr_reqcap & changed) & - (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) { - if_setcapenablebit(ifp, - IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6, 0); - } else { - if_setcapenablebit(ifp, 0, - IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6); - } - } - if (changed & (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6)) { - if ((ifr->ifr_reqcap & changed) & - (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6)) { - if_setcapenablebit(ifp, - IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6, 0); - } else { - if_setcapenablebit(ifp, 0, - IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6); - } + if ((changed & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) != 0) + if_togglecapenable(ifp, IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6); + if ((changed & (IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6)) != 0) { + if_togglecapenable(ifp, IFCAP_TXCSUM | IFCAP_TXCSUM_IPV6); + if_togglehwassist(ifp, DPAA2_CSUM_TX_OFFLOAD); } rc = dpaa2_ni_setup_if_caps(sc); @@ -2953,6 +2961,8 @@ dpaa2_ni_tx(struct dpaa2_ni_softc *sc, struct dpaa2_channel *ch, bus_dma_segment_t segs[DPAA2_TX_SEGLIMIT]; int rc, nsegs; int error; + int len; + bool mcast; mtx_assert(&tx->lock, MA_NOTOWNED); mtx_lock(&tx->lock); @@ -2967,6 +2977,8 @@ dpaa2_ni_tx(struct dpaa2_ni_softc *sc, struct dpaa2_channel *ch, buf->m = m; sgt = buf->sgt; } + len = m->m_pkthdr.len; + mcast = (m->m_flags & M_MCAST) != 0; #if defined(INVARIANTS) struct dpaa2_ni_tx_ring *btx = (struct dpaa2_ni_tx_ring *)buf->opt; @@ -2984,6 +2996,7 @@ dpaa2_ni_tx(struct dpaa2_ni_softc *sc, struct dpaa2_channel *ch, if (md == NULL) { device_printf(dev, "%s: m_collapse() failed\n", __func__); fq->chan->tx_dropped++; + if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); goto err; } @@ -2994,17 +3007,23 @@ dpaa2_ni_tx(struct dpaa2_ni_softc *sc, struct dpaa2_channel *ch, device_printf(dev, "%s: bus_dmamap_load_mbuf_sg() " "failed: error=%d\n", __func__, error); fq->chan->tx_dropped++; + if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); goto err; } } - error = dpaa2_ni_build_fd(sc, tx, buf, segs, nsegs, &fd); + error = dpaa2_fd_build(dev, sc->tx_data_off, buf, segs, nsegs, &fd); if (__predict_false(error != 0)) { device_printf(dev, "%s: failed to build frame descriptor: " "error=%d\n", __func__, error); fq->chan->tx_dropped++; + if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); goto err_unload; - } + } else + sc->tx_sg_frames++; /* for sysctl(9) */ + + bus_dmamap_sync(buf->dmat, buf->dmap, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(sgt->dmat, sgt->dmap, BUS_DMASYNC_PREWRITE); /* TODO: Enqueue several frames in a single command */ for (int i = 0; i < DPAA2_NI_ENQUEUE_RETRIES; i++) { @@ -3015,13 +3034,15 @@ dpaa2_ni_tx(struct dpaa2_ni_softc *sc, struct dpaa2_channel *ch, } } - bus_dmamap_sync(buf->dmat, buf->dmap, BUS_DMASYNC_PREWRITE); - bus_dmamap_sync(sgt->dmat, sgt->dmap, BUS_DMASYNC_PREWRITE); - if (rc != 1) { fq->chan->tx_dropped++; + if_inc_counter(sc->ifp, IFCOUNTER_OERRORS, 1); goto err_unload; } else { + if (mcast) + if_inc_counter(sc->ifp, IFCOUNTER_OMCASTS, 1); + if_inc_counter(sc->ifp, IFCOUNTER_OPACKETS, 1); + if_inc_counter(sc->ifp, IFCOUNTER_OBYTES, len); fq->chan->tx_frames++; } return; @@ -3127,22 +3148,34 @@ dpaa2_ni_consume_frames(struct dpaa2_channel *chan, struct dpaa2_ni_fq **src, * @brief Receive frames. */ static int -dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *fd, - struct dpaa2_ni_rx_ctx *ctx) +dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, + struct dpaa2_fd *fd, struct dpaa2_ni_rx_ctx *ctx) { - bus_addr_t paddr = (bus_addr_t)fd->addr; - struct dpaa2_fa *fa = (struct dpaa2_fa *)PHYS_TO_DMAP(paddr); - struct dpaa2_buf *buf = fa->buf; - struct dpaa2_channel *bch = (struct dpaa2_channel *)buf->opt; - struct dpaa2_ni_softc *sc = device_get_softc(bch->ni_dev); + bus_addr_t paddr; + struct dpaa2_swa *swa; + struct dpaa2_buf *buf; + struct dpaa2_channel *bch; + struct dpaa2_ni_softc *sc; struct dpaa2_bp_softc *bpsc; struct mbuf *m; device_t bpdev; bus_addr_t released[DPAA2_SWP_BUFS_PER_CMD]; void *buf_data; int buf_len, error, released_n = 0; + bool update_csum_flags; - KASSERT(fa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); + error = dpaa2_fa_get_swa(fd, &swa); + if (__predict_false(error != 0)) + panic("%s: frame has no software annotation: error=%d", + __func__, error); + + paddr = (bus_addr_t)fd->addr; + buf = swa->buf; + bch = (struct dpaa2_channel *)buf->opt; + sc = device_get_softc(bch->ni_dev); + update_csum_flags = true; + + KASSERT(swa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); /* * NOTE: Current channel might not be the same as the "buffer" channel * and it's fine. It must not be NULL though. @@ -3154,7 +3187,15 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *f __func__, paddr, buf->paddr); } - switch (dpaa2_ni_fd_err(fd)) { + switch (dpaa2_fd_err(fd)) { + case 0: + /* + * FD[ERR] = 0 value is reserved to indicate that there is no + * error encoded in this field. See 3.4.5 Error handling, + * LX2160A DPAA2 Low-Level Hardware Reference Manual, Rev. 0, + * 06/2020. + */ + break; case 1: /* Enqueue rejected by QMan */ sc->rx_enq_rej_frames++; break; @@ -3162,9 +3203,11 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *f sc->rx_ieoi_err_frames++; break; default: + sc->rx_other_err_frames++; break; } - switch (dpaa2_ni_fd_format(fd)) { + + switch (dpaa2_fd_format(fd)) { case DPAA2_FD_SINGLE: sc->rx_single_buf_frames++; break; @@ -3172,6 +3215,7 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *f sc->rx_sg_buf_frames++; break; default: + update_csum_flags = false; break; } @@ -3180,9 +3224,11 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *f bus_dmamap_sync(buf->dmat, buf->dmap, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(buf->dmat, buf->dmap); + m = buf->m; - buf_len = dpaa2_ni_fd_data_len(fd); - buf_data = (uint8_t *)buf->vaddr + dpaa2_ni_fd_offset(fd); + buf_len = dpaa2_fd_data_len(fd); + buf_data = (uint8_t *)buf->vaddr + dpaa2_fd_offset(fd); + /* Prepare buffer to be re-cycled */ buf->m = NULL; buf->paddr = 0; @@ -3200,6 +3246,15 @@ dpaa2_ni_rx(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *f m->m_pkthdr.rcvif = sc->ifp; m->m_pkthdr.flowid = fq->fqid; M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE); + if_inc_counter(sc->ifp, IFCOUNTER_IPACKETS, 1); + + if (update_csum_flags && ((if_getcapenable(sc->ifp) & (IFCAP_RXCSUM | + IFCAP_RXCSUM_IPV6)) != 0)) { + error = dpaa2_ni_update_csum_flags(fd, m); + if (error != 0) + device_printf(sc->dev, "%s: failed to update checksum " + "flags: error=%d\n", __func__, error); + } if (ctx->head == NULL) { KASSERT(ctx->tail == NULL, ("%s: tail already given?", __func__)); @@ -3269,16 +3324,26 @@ static int dpaa2_ni_rx_err(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *fd) { - bus_addr_t paddr = (bus_addr_t)fd->addr; - struct dpaa2_fa *fa = (struct dpaa2_fa *)PHYS_TO_DMAP(paddr); - struct dpaa2_buf *buf = fa->buf; - struct dpaa2_channel *bch = (struct dpaa2_channel *)buf->opt; - struct dpaa2_ni_softc *sc = device_get_softc(bch->ni_dev); + bus_addr_t paddr; + struct dpaa2_swa *swa; + struct dpaa2_buf *buf; + struct dpaa2_channel *bch; + struct dpaa2_ni_softc *sc; device_t bpdev; struct dpaa2_bp_softc *bpsc; int error; - KASSERT(fa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); + error = dpaa2_fa_get_swa(fd, &swa); + if (__predict_false(error != 0)) + panic("%s: frame has no software annotation: error=%d", + __func__, error); + + paddr = (bus_addr_t)fd->addr; + buf = swa->buf; + bch = (struct dpaa2_channel *)buf->opt; + sc = device_get_softc(bch->ni_dev); + + KASSERT(swa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); /* * NOTE: Current channel might not be the same as the "buffer" channel * and it's fine. It must not be NULL though. @@ -3312,14 +3377,26 @@ static int dpaa2_ni_tx_conf(struct dpaa2_channel *ch, struct dpaa2_ni_fq *fq, struct dpaa2_fd *fd) { - bus_addr_t paddr = (bus_addr_t)fd->addr; - struct dpaa2_fa *fa = (struct dpaa2_fa *)PHYS_TO_DMAP(paddr); - struct dpaa2_buf *buf = fa->buf; - struct dpaa2_buf *sgt = buf->sgt; - struct dpaa2_ni_tx_ring *tx = (struct dpaa2_ni_tx_ring *)buf->opt; - struct dpaa2_channel *bch = tx->fq->chan; - - KASSERT(fa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); + bus_addr_t paddr; + struct dpaa2_swa *swa; + struct dpaa2_buf *buf; + struct dpaa2_buf *sgt; + struct dpaa2_ni_tx_ring *tx; + struct dpaa2_channel *bch; + int error; + + error = dpaa2_fa_get_swa(fd, &swa); + if (__predict_false(error != 0)) + panic("%s: frame has no software annotation: error=%d", + __func__, error); + + paddr = (bus_addr_t)fd->addr; + buf = swa->buf; + sgt = buf->sgt; + tx = (struct dpaa2_ni_tx_ring *)buf->opt; + bch = tx->fq->chan; + + KASSERT(swa->magic == DPAA2_MAGIC, ("%s: wrong magic", __func__)); KASSERT(tx != NULL, ("%s: Tx ring is NULL", __func__)); KASSERT(sgt != NULL, ("%s: S/G table is NULL", __func__)); /* @@ -3368,102 +3445,6 @@ dpaa2_ni_cmp_api_version(struct dpaa2_ni_softc *sc, uint16_t major, } /** - * @brief Build a DPAA2 frame descriptor. - */ -static int -dpaa2_ni_build_fd(struct dpaa2_ni_softc *sc, struct dpaa2_ni_tx_ring *tx, - struct dpaa2_buf *buf, bus_dma_segment_t *segs, int nsegs, struct dpaa2_fd *fd) -{ - struct dpaa2_buf *sgt = buf->sgt; - struct dpaa2_sg_entry *sge; - struct dpaa2_fa *fa; - int i, error; - - KASSERT(nsegs <= DPAA2_TX_SEGLIMIT, ("%s: too many segments", __func__)); - KASSERT(buf->opt != NULL, ("%s: no Tx ring?", __func__)); - KASSERT(sgt != NULL, ("%s: no S/G table?", __func__)); - KASSERT(sgt->vaddr != NULL, ("%s: no S/G vaddr?", __func__)); - - memset(fd, 0, sizeof(*fd)); - - /* Populate and map S/G table */ - if (__predict_true(nsegs <= DPAA2_TX_SEGLIMIT)) { - sge = (struct dpaa2_sg_entry *)sgt->vaddr + sc->tx_data_off; - for (i = 0; i < nsegs; i++) { - sge[i].addr = (uint64_t)segs[i].ds_addr; - sge[i].len = (uint32_t)segs[i].ds_len; - sge[i].offset_fmt = 0u; - } - sge[i-1].offset_fmt |= 0x8000u; /* set final entry flag */ - - KASSERT(sgt->paddr == 0, ("%s: paddr(%#jx) != 0", __func__, - sgt->paddr)); - - error = bus_dmamap_load(sgt->dmat, sgt->dmap, sgt->vaddr, - DPAA2_TX_SGT_SZ, dpaa2_dmamap_oneseg_cb, &sgt->paddr, - BUS_DMA_NOWAIT); - if (__predict_false(error != 0)) { - device_printf(sc->dev, "%s: bus_dmamap_load() failed: " - "error=%d\n", __func__, error); - return (error); - } - - buf->paddr = sgt->paddr; - buf->vaddr = sgt->vaddr; - sc->tx_sg_frames++; /* for sysctl(9) */ - } else { - return (EINVAL); - } - - fa = (struct dpaa2_fa *)sgt->vaddr; - fa->magic = DPAA2_MAGIC; - fa->buf = buf; - - fd->addr = buf->paddr; - fd->data_length = (uint32_t)buf->m->m_pkthdr.len; - fd->bpid_ivp_bmt = 0; - fd->offset_fmt_sl = 0x2000u | sc->tx_data_off; - fd->ctrl = 0x00800000u; - - return (0); -} - -static int -dpaa2_ni_fd_err(struct dpaa2_fd *fd) -{ - return ((fd->ctrl >> DPAA2_NI_FD_ERR_SHIFT) & DPAA2_NI_FD_ERR_MASK); -} - -static uint32_t -dpaa2_ni_fd_data_len(struct dpaa2_fd *fd) -{ - if (dpaa2_ni_fd_short_len(fd)) { - return (fd->data_length & DPAA2_NI_FD_LEN_MASK); - } - return (fd->data_length); -} - -static int -dpaa2_ni_fd_format(struct dpaa2_fd *fd) -{ - return ((enum dpaa2_fd_format)((fd->offset_fmt_sl >> - DPAA2_NI_FD_FMT_SHIFT) & DPAA2_NI_FD_FMT_MASK)); -} - -static bool -dpaa2_ni_fd_short_len(struct dpaa2_fd *fd) -{ - return (((fd->offset_fmt_sl >> DPAA2_NI_FD_SL_SHIFT) - & DPAA2_NI_FD_SL_MASK) == 1); -} - -static int -dpaa2_ni_fd_offset(struct dpaa2_fd *fd) -{ - return (fd->offset_fmt_sl & DPAA2_NI_FD_OFFSET_MASK); -} - -/** * @brief Collect statistics of the network interface. */ static int @@ -3477,7 +3458,7 @@ dpaa2_ni_collect_stats(SYSCTL_HANDLER_ARGS) struct dpaa2_devinfo *rcinfo = device_get_ivars(pdev); struct dpaa2_devinfo *dinfo = device_get_ivars(dev); struct dpaa2_cmd cmd; - uint64_t cnt[DPAA2_NI_STAT_COUNTERS]; + uint64_t cnt[DPAA2_NI_STAT_COUNTERS_PER_PAGE]; uint64_t result = 0; uint16_t rc_token, ni_token; int error; @@ -3510,6 +3491,71 @@ exit: } static int +dpaa2_ni_sysctl_link_state(SYSCTL_HANDLER_ARGS) +{ + struct dpaa2_ni_softc *sc; + struct dpaa2_devinfo *rcinfo; + struct dpaa2_devinfo *dinfo; + struct dpaa2_cmd cmd; + struct dpaa2_ni_link_state ls; + struct sbuf s; + int error; + uint16_t rc_token, ni_token; + + if (req->newptr) + return (EPERM); + + sc = (struct dpaa2_ni_softc *)arg1; + + rcinfo = device_get_ivars(device_get_parent(sc->dev)); + dinfo = device_get_ivars(sc->dev); + + DPAA2_CMD_INIT(&cmd); + + error = DPAA2_CMD_RC_OPEN(sc->dev, sc->dev, &cmd, rcinfo->id, &rc_token); + if (error != 0) { + device_printf(sc->dev, "%s: failed to open resource container: " + "id=%d, error=%d\n", __func__, rcinfo->id, error); + goto exit; + } + error = DPAA2_CMD_NI_OPEN(sc->dev, sc->dev, &cmd, dinfo->id, &ni_token); + if (error != 0) { + device_printf(sc->dev, "%s: failed to open network interface: " + "id=%d, error=%d\n", __func__, dinfo->id, error); + goto close_rc; + } + + error = DPAA2_CMD_NI_GET_LINK_STATE(sc->dev, sc->dev, &cmd, &ls); + + (void)DPAA2_CMD_NI_CLOSE(sc->dev, sc->dev, DPAA2_CMD_TK(&cmd, ni_token)); +close_rc: + (void)DPAA2_CMD_RC_CLOSE(sc->dev, sc->dev, DPAA2_CMD_TK(&cmd, rc_token)); + + if (error != 0) + goto exit; + +#define NI_LINK_STATE_OPTIONS_BITS \ + "\20\1AUTONEG\2HDX\3PAUSE\4ASYM_PAUSE" + + sbuf_new_for_sysctl(&s, NULL, 1024, req); + sbuf_putc(&s, '\n'); + sbuf_printf(&s, "Link State: %s (%s)\n", ls.link_up ? "UP" : "DOWN", + ls.state_valid ? "VALID" : "IGNORE"); + sbuf_printf(&s, "Link Rate: %ju\n", (uintmax_t)ls.rate); + sbuf_printf(&s, "Link Options: %b\n", + (int)ls.options, NI_LINK_STATE_OPTIONS_BITS); + sbuf_printf(&s, "Link Speed Capabilities: %#018jx\n", + (uintmax_t)ls.sup_speeds); + sbuf_printf(&s, "Link Speed Advertised for autoneg: %#018jx\n", + (uintmax_t)ls.adv_speeds); + sbuf_finish(&s); + sbuf_delete(&s); + +exit: + return (error); +} + +static int dpaa2_ni_collect_buf_num(SYSCTL_HANDLER_ARGS) { struct dpaa2_ni_softc *sc = (struct dpaa2_ni_softc *) arg1; @@ -3716,6 +3762,51 @@ dpaa2_ni_prepare_key_cfg(struct dpkg_profile_cfg *cfg, uint8_t *key_cfg_buf) return (0); } +static int +dpaa2_ni_update_csum_flags(struct dpaa2_fd *fd, struct mbuf *m) +{ + struct dpaa2_hwa_fas fas; + uint32_t status; + int rc; + + if (__predict_false((dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV)) == 0u) + return (EINVAL); + + /* + * XXX-DSL: Frame context of the frame descriptor (FD[FRC]) contains + * an Accelerator ID in the MSbits on some SoCs (e.g. LS1088A), + * but a frame ParseSummary on the others (e.g. LX2160A). + * However, frame annotation valid bits seem to be at the + * same offsets. This is the reason why different accelerators + * are treated the same here. It isn't clear whether this is + * a hardware limitation of the SoCs, version of the firmware + * or DPL configuration. + */ + + rc = dpaa2_fa_get_fas(fd, &fas); + if (rc != 0) + return (rc); + + status = le32toh(fas.status); + rc = 0; + + /* L3 */ + if ((status & DPAA2_FAS_L3CV) != 0) { + m->m_pkthdr.csum_flags |= CSUM_L3_CALC; + if ((status & DPAA2_FAS_L3CE) == 0) + m->m_pkthdr.csum_flags |= CSUM_L3_VALID; + } + /* L4 */ + if ((status & DPAA2_FAS_L4CV) != 0) { + m->m_pkthdr.csum_flags |= CSUM_L4_CALC; + m->m_pkthdr.csum_data = 0xffff; + if ((status & DPAA2_FAS_L4CE) == 0) + m->m_pkthdr.csum_flags |= CSUM_L4_VALID; + } + + return (rc); +} + static device_method_t dpaa2_ni_methods[] = { /* Device interface */ DEVMETHOD(device_probe, dpaa2_ni_probe), diff --git a/sys/dev/dpaa2/dpaa2_ni.h b/sys/dev/dpaa2/dpaa2_ni.h index 6fb0673fac09..51da539dfa66 100644 --- a/sys/dev/dpaa2/dpaa2_ni.h +++ b/sys/dev/dpaa2/dpaa2_ni.h @@ -1,8 +1,9 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright © 2021-2023 Dmitry Salychev - * Copyright © 2022 Mathew McBride + * Copyright (c) 2021-2023 Dmitry Salychev + * Copyright (c) 2022 Mathew McBride + * Copyright (c) 2026 Bjoern A. Zeeb * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -68,9 +69,8 @@ #define DPAA2_NI_BUFS_PER_TX (1 << 7) #define DPAA2_NI_MAX_BPTX (1 << 8) -/* Number of the DPNI statistics counters. */ -#define DPAA2_NI_STAT_COUNTERS 7u -#define DPAA2_NI_STAT_SYSCTLS 9u +/* Number of the DPNI statistics counters per page. */ +#define DPAA2_NI_STAT_COUNTERS_PER_PAGE 7u /* Error and status bits in the frame annotation status word. */ #define DPAA2_NI_FAS_DISC 0x80000000 /* debug frame */ @@ -466,6 +466,7 @@ struct dpaa2_ni_softc { uint64_t rx_sg_buf_frames; uint64_t rx_enq_rej_frames; uint64_t rx_ieoi_err_frames; + uint64_t rx_other_err_frames; uint64_t tx_single_buf_frames; uint64_t tx_sg_frames; @@ -490,8 +491,9 @@ struct dpaa2_ni_softc { struct dpaa2_channel *channels[DPAA2_MAX_CHANNELS]; struct dpaa2_ni_fq rxe_queue; /* one per DPNI */ + /* sysctl(9) */ struct dpaa2_atomic buf_num; - struct dpaa2_atomic buf_free; /* for sysctl(9) only */ + struct dpaa2_atomic buf_free; int irq_rid[DPAA2_NI_MSI_COUNT]; struct resource *irq_res; diff --git a/sys/dev/dpaa2/dpaa2_rc.c b/sys/dev/dpaa2/dpaa2_rc.c index 5e4346ad6969..f361d6655854 100644 --- a/sys/dev/dpaa2/dpaa2_rc.c +++ b/sys/dev/dpaa2/dpaa2_rc.c @@ -1391,9 +1391,10 @@ dpaa2_rc_ni_get_link_state(device_t dev, device_t child, struct dpaa2_cmd *cmd, { struct __packed link_state_resp { uint32_t _reserved1; - uint32_t flags; + uint8_t flags; + uint8_t _reserved2[3]; uint32_t rate; - uint32_t _reserved2; + uint32_t _reserved3; uint64_t options; uint64_t supported; uint64_t advert; @@ -1890,7 +1891,7 @@ dpaa2_rc_ni_get_statistics(device_t dev, device_t child, struct dpaa2_cmd *cmd, uint16_t param; } *args; struct __packed get_statistics_resp { - uint64_t cnt[7]; + uint64_t cnt[DPAA2_NI_STAT_COUNTERS_PER_PAGE]; } *resp; struct dpaa2_mcp *portal = dpaa2_rc_select_portal(dev, child); int error; @@ -1907,7 +1908,7 @@ dpaa2_rc_ni_get_statistics(device_t dev, device_t child, struct dpaa2_cmd *cmd, error = dpaa2_rc_exec_cmd(portal, cmd, CMDID_NI_GET_STATISTICS); if (!error) { resp = (struct get_statistics_resp *) &cmd->params[0]; - for (int i = 0; i < DPAA2_NI_STAT_COUNTERS; i++) + for (int i = 0; i < DPAA2_NI_STAT_COUNTERS_PER_PAGE; i++) cnt[i] = resp->cnt[i]; } diff --git a/sys/dev/dpaa2/dpaa2_swp.h b/sys/dev/dpaa2/dpaa2_swp.h index 1b1383b4241f..20980c6b71b7 100644 --- a/sys/dev/dpaa2/dpaa2_swp.h +++ b/sys/dev/dpaa2/dpaa2_swp.h @@ -35,6 +35,7 @@ #include "dpaa2_types.h" #include "dpaa2_buf.h" #include "dpaa2_bp.h" +#include "dpaa2_frame.h" /* * DPAA2 QBMan software portal. @@ -200,10 +201,8 @@ #define DPAA2_EQ_DESC_SIZE 32u /* Enqueue Command Descriptor */ #define DPAA2_FDR_DESC_SIZE 32u /* Descriptor of the FDR */ -#define DPAA2_FD_SIZE 32u /* Frame Descriptor */ #define DPAA2_FDR_SIZE 64u /* Frame Dequeue Response */ #define DPAA2_SCN_SIZE 16u /* State Change Notification */ -#define DPAA2_FA_SIZE 64u /* SW Frame Annotation */ #define DPAA2_SGE_SIZE 16u /* S/G table entry */ #define DPAA2_DQ_SIZE 64u /* Dequeue Response */ #define DPAA2_SWP_CMD_SIZE 64u /* SWP Command */ @@ -285,54 +284,6 @@ struct dpaa2_scn { CTASSERT(sizeof(struct dpaa2_scn) == DPAA2_SCN_SIZE); /** - * @brief DPAA2 frame descriptor. - * - * addr: Memory address of the start of the buffer holding the - * frame data or the buffer containing the scatter/gather - * list. - * data_length: Length of the frame data (in bytes). - * bpid_ivp_bmt: Buffer pool ID (14 bit + BMT bit + IVP bit) - * offset_fmt_sl: Frame data offset, frame format and short-length fields. - * frame_ctx: Frame context. This field allows the sender of a frame - * to communicate some out-of-band information to the - * receiver of the frame. - * ctrl: Control bits (ERR, CBMT, ASAL, PTAC, DROPP, SC, DD). - * flow_ctx: Frame flow context. Associates the frame with a flow - * structure. QMan may use the FLC field for 3 purposes: - * stashing control, order definition point identification, - * and enqueue replication control. - */ -struct dpaa2_fd { - uint64_t addr; - uint32_t data_length; - uint16_t bpid_ivp_bmt; - uint16_t offset_fmt_sl; - uint32_t frame_ctx; - uint32_t ctrl; - uint64_t flow_ctx; -} __packed; -CTASSERT(sizeof(struct dpaa2_fd) == DPAA2_FD_SIZE); - -/** - * @brief DPAA2 frame annotation. - */ -struct dpaa2_fa { - uint32_t magic; - struct dpaa2_buf *buf; -#ifdef __notyet__ - union { - struct { /* Tx frame annotation */ - struct dpaa2_ni_tx_ring *tx; - }; - struct { /* Rx frame annotation */ - uint64_t _notused; - }; - }; -#endif -} __packed; -CTASSERT(sizeof(struct dpaa2_fa) <= DPAA2_FA_SIZE); - -/** * @brief DPAA2 scatter/gather entry. */ struct dpaa2_sg_entry { diff --git a/sys/dev/dpaa2/dpaa2_types.h b/sys/dev/dpaa2/dpaa2_types.h index dbfac9ce0a40..dc1c232c09c2 100644 --- a/sys/dev/dpaa2/dpaa2_types.h +++ b/sys/dev/dpaa2/dpaa2_types.h @@ -40,6 +40,11 @@ #define DPAA2_MAX_CHANNELS 16 /* CPU cores */ #define DPAA2_MAX_TCS 8 /* Traffic classes */ +#define DPAA2_TX_SEGLIMIT (16u) /* for 64 KiB frames */ +#define DPAA2_TX_SEG_SZ (PAGE_SIZE) +#define DPAA2_TX_SEGS_MAXSZ (DPAA2_TX_SEGLIMIT * DPAA2_TX_SEG_SZ) +#define DPAA2_TX_SGT_SZ (PAGE_SIZE) /* in bytes */ + /** * @brief Types of the DPAA2 devices. */ diff --git a/sys/dev/dpms/dpms.c b/sys/dev/dpms/dpms.c index 05397e880b85..659b852c046e 100644 --- a/sys/dev/dpms/dpms.c +++ b/sys/dev/dpms/dpms.c @@ -106,7 +106,7 @@ static device_method_t dpms_methods[] = { DEVMETHOD(device_detach, dpms_detach), DEVMETHOD(device_suspend, dpms_suspend), DEVMETHOD(device_resume, dpms_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t dpms_driver = { diff --git a/sys/dev/drm2/ttm/ttm_bo_util.c b/sys/dev/drm2/ttm/ttm_bo_util.c index 3948075ad104..4d4de90b6525 100644 --- a/sys/dev/drm2/ttm/ttm_bo_util.c +++ b/sys/dev/drm2/ttm/ttm_bo_util.c @@ -500,7 +500,7 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, map->bo_kmap_type = ttm_bo_map_kmap; map->page = ttm->pages[start_page]; map->sf = sf_buf_alloc(map->page, 0); - map->virtual = (void *)sf_buf_kva(map->sf); + map->virtual = sf_buf_kva(map->sf); } else { /* * We need to use vmap to get the desired page protection @@ -510,14 +510,14 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo, VM_MEMATTR_DEFAULT : ttm_io_prot(mem->placement); map->bo_kmap_type = ttm_bo_map_vmap; map->num_pages = num_pages; - map->virtual = (void *)kva_alloc(num_pages * PAGE_SIZE); + map->virtual = kva_alloc(num_pages * PAGE_SIZE); if (map->virtual != NULL) { for (i = 0; i < num_pages; i++) { /* XXXKIB hack */ pmap_page_set_memattr(ttm->pages[start_page + i], prot); } - pmap_qenter((vm_offset_t)map->virtual, + pmap_qenter(map->virtual, &ttm->pages[start_page], num_pages); } } @@ -571,9 +571,8 @@ void ttm_bo_kunmap(struct ttm_bo_kmap_obj *map) pmap_unmapdev(map->virtual, map->size); break; case ttm_bo_map_vmap: - pmap_qremove((vm_offset_t)(map->virtual), map->num_pages); - kva_free((vm_offset_t)map->virtual, - map->num_pages * PAGE_SIZE); + pmap_qremove(map->virtual, map->num_pages); + kva_free(map->virtual, map->num_pages * PAGE_SIZE); break; case ttm_bo_map_kmap: sf_buf_free(map->sf); diff --git a/sys/dev/dwc/dwc1000_core.c b/sys/dev/dwc/dwc1000_core.c index ba895f991b50..ab1d50c61150 100644 --- a/sys/dev/dwc/dwc1000_core.c +++ b/sys/dev/dwc/dwc1000_core.c @@ -238,7 +238,7 @@ dwc1000_enable_csum_offload(struct dwc_softc *sc) DWC_ASSERT_LOCKED(sc); reg = READ4(sc, MAC_CONFIGURATION); - if ((if_getcapenable(sc->ifp) & IFCAP_RXCSUM) != 0) + if ((if_getcapenable(sc->ifp) & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) != 0) reg |= CONF_IPC; else reg &= ~CONF_IPC; diff --git a/sys/dev/dwc/dwc1000_dma.c b/sys/dev/dwc/dwc1000_dma.c index 44b9f0d114bf..6457503d2a7f 100644 --- a/sys/dev/dwc/dwc1000_dma.c +++ b/sys/dev/dwc/dwc1000_dma.c @@ -248,7 +248,7 @@ dma1000_setup_txbuf(struct dwc_softc *sc, int idx, struct mbuf **mp) struct bus_dma_segment segs[TX_MAP_MAX_SEGS]; int error, nsegs; struct mbuf * m; - uint32_t flags = 0; + uint32_t flags; int i; int last; @@ -276,19 +276,12 @@ dma1000_setup_txbuf(struct dwc_softc *sc, int idx, struct mbuf **mp) m = *mp; - if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0) { - if ((m->m_pkthdr.csum_flags & (CSUM_TCP|CSUM_UDP)) != 0) { - if (!sc->dma_ext_desc) - flags = NTDESC1_CIC_FULL; - else - flags = ETDESC0_CIC_FULL; - } else { - if (!sc->dma_ext_desc) - flags = NTDESC1_CIC_HDR; - else - flags = ETDESC0_CIC_HDR; - } - } + if ((m->m_pkthdr.csum_flags & (CSUM_DELAY_DATA | CSUM_DELAY_DATA_IPV6)) != 0) + flags = sc->dma_ext_desc ? ETDESC0_CIC_SEG : NTDESC1_CIC_SEG; + else if ((m->m_pkthdr.csum_flags & CSUM_IP) != 0) + flags = sc->dma_ext_desc ? ETDESC0_CIC_HDR : NTDESC1_CIC_HDR; + else + flags = sc->dma_ext_desc ? ETDESC0_CIC_NONE : NTDESC1_CIC_NONE; bus_dmamap_sync(sc->txbuf_tag, sc->txbuf_map[idx].map, BUS_DMASYNC_PREWRITE); @@ -397,8 +390,8 @@ dwc_rxfinish_one(struct dwc_softc *sc, struct dwc_hwdesc *desc, m->m_len = len; if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); - if ((if_getcapenable(ifp) & IFCAP_RXCSUM) != 0 && - (rdesc0 & RDESC0_FT) != 0) { + if ((if_getcapenable(ifp) & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) != 0 && + (rdesc0 & RDESC0_FT) != 0) { m->m_pkthdr.csum_flags = CSUM_IP_CHECKED; if ((rdesc0 & RDESC0_ICE) == 0) m->m_pkthdr.csum_flags |= CSUM_IP_VALID; diff --git a/sys/dev/dwc/if_dwc.c b/sys/dev/dwc/if_dwc.c index 1b4b4be68747..cd8651cc99ff 100644 --- a/sys/dev/dwc/if_dwc.c +++ b/sys/dev/dwc/if_dwc.c @@ -263,14 +263,16 @@ dwc_ioctl(if_t ifp, u_long cmd, caddr_t data) /* No work to do except acknowledge the change took */ if_togglecapenable(ifp, IFCAP_VLAN_MTU); } - if (mask & IFCAP_RXCSUM) - if_togglecapenable(ifp, IFCAP_RXCSUM); - if (mask & IFCAP_TXCSUM) + if (mask & (IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6)) + if_togglecapenable(ifp, IFCAP_RXCSUM | IFCAP_RXCSUM_IPV6); + if (mask & IFCAP_TXCSUM) { if_togglecapenable(ifp, IFCAP_TXCSUM); - if ((if_getcapenable(ifp) & IFCAP_TXCSUM) != 0) - if_sethwassistbits(ifp, CSUM_IP | CSUM_UDP | CSUM_TCP, 0); - else - if_sethwassistbits(ifp, 0, CSUM_IP | CSUM_UDP | CSUM_TCP); + if_togglehwassist(ifp, CSUM_IP | CSUM_DELAY_DATA); + } + if (mask & IFCAP_TXCSUM_IPV6) { + if_togglecapenable(ifp, IFCAP_TXCSUM_IPV6); + if_togglehwassist(ifp, CSUM_DELAY_DATA_IPV6); + } if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { DWC_LOCK(sc); @@ -525,13 +527,13 @@ dwc_attach(device_t dev) sc->txpbl = pbl; if (OF_getencprop(sc->node, "snps,rxpbl", &sc->rxpbl, sizeof(uint32_t)) <= 0) sc->rxpbl = pbl; - if (OF_hasprop(sc->node, "snps,no-pbl-x8") == 1) + if (OF_hasprop(sc->node, "snps,no-pbl-x8")) sc->nopblx8 = true; - if (OF_hasprop(sc->node, "snps,fixed-burst") == 1) + if (OF_hasprop(sc->node, "snps,fixed-burst")) sc->fixed_burst = true; - if (OF_hasprop(sc->node, "snps,mixed-burst") == 1) + if (OF_hasprop(sc->node, "snps,mixed-burst")) sc->mixed_burst = true; - if (OF_hasprop(sc->node, "snps,aal") == 1) + if (OF_hasprop(sc->node, "snps,aal")) sc->aal = true; error = clk_set_assigned(dev, ofw_bus_get_node(dev)); @@ -607,8 +609,8 @@ dwc_attach(device_t dev) if_setinitfn(ifp, dwc_init); if_setsendqlen(ifp, TX_MAP_COUNT - 1); if_setsendqready(sc->ifp); - if_sethwassist(sc->ifp, CSUM_IP | CSUM_UDP | CSUM_TCP); - if_setcapabilities(sc->ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM); + if_sethwassist(sc->ifp, CSUM_IP | CSUM_DELAY_DATA | CSUM_DELAY_DATA_IPV6); + if_setcapabilities(sc->ifp, IFCAP_VLAN_MTU | IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6); if_setcapenable(sc->ifp, if_getcapabilities(sc->ifp)); /* Attach the mii driver. */ @@ -682,7 +684,7 @@ static device_method_t dwc_methods[] = { DEVMETHOD(miibus_writereg, dwc1000_miibus_write_reg), DEVMETHOD(miibus_statchg, dwc1000_miibus_statchg), - { 0, 0 } + DEVMETHOD_END }; driver_t dwc_driver = { diff --git a/sys/dev/e1000/em_txrx.c b/sys/dev/e1000/em_txrx.c index 647255417b3e..b86222e363e9 100644 --- a/sys/dev/e1000/em_txrx.c +++ b/sys/dev/e1000/em_txrx.c @@ -836,6 +836,6 @@ em_determine_rsstype(uint32_t pkt_info) case E1000_RXDADV_RSSTYPE_IPV6_TCP_EX: return M_HASHTYPE_RSS_TCP_IPV6_EX; default: - return M_HASHTYPE_OPAQUE; + return M_HASHTYPE_NONE; } } diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 7d7655a7ae6f..3118b27e8122 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -2106,11 +2106,11 @@ em_if_set_promisc(if_ctx_t ctx, int flags) if (flags & IFF_PROMISC) { reg_rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); - em_if_vlan_filter_disable(sc); /* Turn this on if you want to see bad packets */ if (em_debug_sbp) reg_rctl |= E1000_RCTL_SBP; E1000_WRITE_REG(&sc->hw, E1000_RCTL, reg_rctl); + em_if_vlan_filter_disable(sc); } else { if (flags & IFF_ALLMULTI) { reg_rctl |= E1000_RCTL_MPE; @@ -3225,8 +3225,8 @@ em_reset(if_ctx_t ctx) case e1000_pch_ptp: hw->fc.high_water = 0x5C20; hw->fc.low_water = 0x5048; - hw->fc.pause_time = 0x0650; - hw->fc.refresh_time = 0x0400; + hw->fc.pause_time = 0xFFFF; + hw->fc.refresh_time = 0xFFFF; /* Jumbos need adjusted PBA */ if (if_getmtu(ifp) > ETHERMTU) E1000_WRITE_REG(hw, E1000_PBA, 12); diff --git a/sys/dev/e1000/igb_txrx.c b/sys/dev/e1000/igb_txrx.c index 46fe5c741055..e01bc72cdc55 100644 --- a/sys/dev/e1000/igb_txrx.c +++ b/sys/dev/e1000/igb_txrx.c @@ -573,6 +573,6 @@ igb_determine_rsstype(uint16_t pkt_info) case E1000_RXDADV_RSSTYPE_IPV6_TCP_EX: return M_HASHTYPE_RSS_TCP_IPV6_EX; default: - return M_HASHTYPE_OPAQUE; + return M_HASHTYPE_NONE; } } diff --git a/sys/dev/efidev/efirt.c b/sys/dev/efidev/efirt.c index b55c1c191077..c3ac120c6611 100644 --- a/sys/dev/efidev/efirt.c +++ b/sys/dev/efidev/efirt.c @@ -192,7 +192,7 @@ efi_init(void) return (0); } - efi_systbl = (struct efi_systbl *)efi_phys_to_kva(efi_systbl_phys); + efi_systbl = efi_phys_to_kva(efi_systbl_phys); if (efi_systbl == NULL || efi_systbl->st_hdr.th_sig != EFI_SYSTBL_SIG) { efi_systbl = NULL; if (bootverbose) @@ -243,7 +243,7 @@ efi_init(void) * with an old loader.efi, check if the RS->GetTime function is within * the EFI map, and fail to attach if not. */ - rtdm = (struct efi_rt *)efi_phys_to_kva((uintptr_t)efi_runtime); + rtdm = efi_phys_to_kva((uintptr_t)efi_runtime); if (rtdm == NULL || !efi_is_in_map(map, ndesc, efihdr->descriptor_size, (vm_offset_t)rtdm->rt_gettime)) { if (bootverbose) diff --git a/sys/dev/ena/ena.c b/sys/dev/ena/ena.c index af158b5aea1d..6972c71bd67c 100644 --- a/sys/dev/ena/ena.c +++ b/sys/dev/ena/ena.c @@ -1861,7 +1861,7 @@ ena_setup_io_intr(struct ena_adapter *adapter) adapter->que[i].domain = idx; #else adapter->que[i].domain = -1; -#endif +#endif /* RSS */ } return (0); @@ -2671,11 +2671,11 @@ static int ena_enable_wc(device_t pdev, struct resource *res) { #if defined(__i386) || defined(__amd64) || defined(__aarch64__) - vm_offset_t va; + void *va; vm_size_t len; int rc; - va = (vm_offset_t)rman_get_virtual(res); + va = rman_get_virtual(res); len = rman_get_size(res); /* Enable write combining */ rc = pmap_change_attr(va, len, VM_MEMATTR_WRITE_COMBINING); @@ -2766,8 +2766,7 @@ ena_set_llq_configurations(struct ena_llq_configurations *llq_config, llq_config->llq_num_decs_before_header = ENA_ADMIN_LLQ_NUM_DESCS_BEFORE_HEADER_2; - switch (ena_force_large_llq_header) - { + switch (ena_force_large_llq_header) { case ENA_LLQ_HEADER_SIZE_POLICY_REGULAR: use_large_llq = false; break; diff --git a/sys/dev/ena/ena.h b/sys/dev/ena/ena.h index 3b01605b4ba7..b2156437f847 100644 --- a/sys/dev/ena/ena.h +++ b/sys/dev/ena/ena.h @@ -39,7 +39,7 @@ #define ENA_DRV_MODULE_VER_MAJOR 2 #define ENA_DRV_MODULE_VER_MINOR 8 -#define ENA_DRV_MODULE_VER_SUBMINOR 1 +#define ENA_DRV_MODULE_VER_SUBMINOR 2 #define ENA_DRV_MODULE_NAME "ena" @@ -99,8 +99,8 @@ * of TCP retransmissions. */ #define ENA_TX_BUDGET 128 -/* RX cleanup budget. -1 stands for infinity. */ -#define ENA_RX_BUDGET 256 +/* RX cleanup budget, in descriptors. -1 stands for infinity. */ +#define ENA_RX_DESC_BUDGET 256 /* * How many times we can repeat cleanup in the io irq handling routine if the * RX or TX budget was depleted. diff --git a/sys/dev/ena/ena_datapath.c b/sys/dev/ena/ena_datapath.c index ec64ae9324bf..91e3e3b6e4cd 100644 --- a/sys/dev/ena/ena_datapath.c +++ b/sys/dev/ena/ena_datapath.c @@ -42,8 +42,8 @@ * Static functions prototypes *********************************************************************/ -static int ena_tx_cleanup(struct ena_ring *); -static int ena_rx_cleanup(struct ena_ring *); +static bool ena_tx_cleanup(struct ena_ring *); +static bool ena_rx_cleanup(struct ena_ring *); static inline int ena_get_tx_req_id(struct ena_ring *tx_ring, struct ena_com_io_cq *io_cq, uint16_t *req_id); static void ena_rx_hash_mbuf(struct ena_ring *, struct ena_com_rx_ctx *, @@ -73,7 +73,8 @@ ena_cleanup(void *arg, int pending) struct ena_com_io_cq *io_cq; struct ena_eth_io_intr_reg intr_reg; int qid, ena_qid; - int txc, rxc, i; + int i; + bool rx_again, tx_again; tx_ring = que->tx_ring; rx_ring = que->rx_ring; @@ -97,14 +98,14 @@ ena_cleanup(void *arg, int pending) atomic_store_8(&rx_ring->first_interrupt, 1); for (i = 0; i < ENA_CLEAN_BUDGET; ++i) { - rxc = ena_rx_cleanup(rx_ring); - txc = ena_tx_cleanup(tx_ring); + rx_again = ena_rx_cleanup(rx_ring); + tx_again = ena_tx_cleanup(tx_ring); if (unlikely(((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) || (ENA_FLAG_ISSET(ENA_FLAG_TRIGGER_RESET, adapter)))) return; - if ((txc != ENA_TX_BUDGET) && (rxc != ENA_RX_BUDGET)) + if (!rx_again && !tx_again) break; } @@ -236,7 +237,7 @@ ena_get_tx_req_id(struct ena_ring *tx_ring, struct ena_com_io_cq *io_cq, * TX_COMMIT. The first check of free descriptor is performed before the actual * loop, then repeated at the loop end. **/ -static int +static bool ena_tx_cleanup(struct ena_ring *tx_ring) { struct ena_adapter *adapter; @@ -248,7 +249,6 @@ ena_tx_cleanup(struct ena_ring *tx_ring) int rc; int commit = ENA_TX_COMMIT; int budget = ENA_TX_BUDGET; - int work_done; bool above_thresh; adapter = tx_ring->que->adapter; @@ -302,10 +302,8 @@ ena_tx_cleanup(struct ena_ring *tx_ring) } } while (likely(--budget)); - work_done = ENA_TX_BUDGET - budget; - ena_log_io(adapter->pdev, DBG, "tx: q %d done. total pkts: %d\n", - tx_ring->qid, work_done); + tx_ring->qid, ENA_TX_BUDGET - budget); /* If there is still something to commit update ring state */ if (likely(commit != ENA_TX_COMMIT)) { @@ -337,7 +335,7 @@ ena_tx_cleanup(struct ena_ring *tx_ring) tx_ring->tx_last_cleanup_ticks = ticks; - return (work_done); + return (budget == 0); } static void @@ -555,7 +553,7 @@ ena_rx_checksum(struct ena_ring *rx_ring, struct ena_com_rx_ctx *ena_rx_ctx, * ena_rx_cleanup - handle rx irq * @arg: ring for which irq is being handled **/ -static int +static bool ena_rx_cleanup(struct ena_ring *rx_ring) { struct ena_adapter *adapter; @@ -573,7 +571,7 @@ ena_rx_cleanup(struct ena_ring *rx_ring) uint32_t do_if_input = 0; unsigned int qid; int rc, i; - int budget = ENA_RX_BUDGET; + int budget = (ENA_RX_DESC_BUDGET == -1) ? INT_MAX : ENA_RX_DESC_BUDGET; #ifdef DEV_NETMAP int done; #endif /* DEV_NETMAP */ @@ -682,7 +680,14 @@ ena_rx_cleanup(struct ena_ring *rx_ring) counter_u64_add_protected(rx_ring->rx_stats.cnt, 1); counter_u64_add_protected(adapter->hw_stats.rx_packets, 1); counter_exit(); - } while (--budget); + + /* + * Adjust our budget; note that we count descriptors, not + * packets, since we need to ensure we don't run out of rx + * buffers when receiving jumbos. + */ + budget -= ena_rx_ctx.descs; + } while (budget > 0); rx_ring->next_to_clean = next_to_clean; @@ -697,7 +702,7 @@ ena_rx_cleanup(struct ena_ring *rx_ring) tcp_lro_flush_all(&rx_ring->lro); - return (ENA_RX_BUDGET - budget); + return (budget <= 0); } static void diff --git a/sys/dev/ena/ena_netmap.c b/sys/dev/ena/ena_netmap.c index 8a220373ec3f..0e8c95fb289a 100644 --- a/sys/dev/ena/ena_netmap.c +++ b/sys/dev/ena/ena_netmap.c @@ -223,9 +223,11 @@ ena_ring_in_netmap(struct ena_adapter *adapter, int qid, enum txrx x) if (if_getcapenable(adapter->ifp) & IFCAP_NETMAP) { na = NA(adapter->ifp); - kring = (x == NR_RX) ? na->rx_rings[qid] : na->tx_rings[qid]; - if (kring->nr_mode == NKR_NETMAP_ON) - return true; + if (na->na_flags & NAF_NATIVE) { + kring = (x == NR_RX) ? na->rx_rings[qid] : na->tx_rings[qid]; + if (kring->nr_mode == NKR_NETMAP_ON) + return true; + } } return false; } diff --git a/sys/dev/ena/ena_rss.h b/sys/dev/ena/ena_rss.h index b7c5181397af..d1236ef26c33 100644 --- a/sys/dev/ena/ena_rss.h +++ b/sys/dev/ena/ena_rss.h @@ -35,11 +35,10 @@ #include "opt_rss.h" #include <sys/types.h> +#include "ena.h" #include <net/rss_config.h> -#include "ena.h" - #define ENA_RX_RSS_MSG_RECORD_SZ 8 struct ena_indir { diff --git a/sys/dev/etherswitch/e6000sw/e6000sw.c b/sys/dev/etherswitch/e6000sw/e6000sw.c index 7e9193f4ba47..248a13952d35 100644 --- a/sys/dev/etherswitch/e6000sw/e6000sw.c +++ b/sys/dev/etherswitch/e6000sw/e6000sw.c @@ -302,6 +302,10 @@ e6000sw_probe(device_t dev) description = "Marvell 88E6352"; sc->num_ports = 7; break; + case MV88E6171: + description = "Marvell 88E6171"; + sc->num_ports = 7; + break; case MV88E6172: description = "Marvell 88E6172"; sc->num_ports = 7; @@ -571,6 +575,8 @@ e6000sw_attach(device_t dev) } for (child = OF_child(ports); child != 0; child = OF_peer(child)) { + if (!ofw_bus_node_status_okay(child)) + continue; err = e6000sw_parse_child_fdt(sc, child, &port); if (err != 0) { device_printf(sc->dev, "failed to parse DTS\n"); diff --git a/sys/dev/etherswitch/e6000sw/e6000swreg.h b/sys/dev/etherswitch/e6000sw/e6000swreg.h index ec4503faeec5..aef79ad9de5d 100644 --- a/sys/dev/etherswitch/e6000sw/e6000swreg.h +++ b/sys/dev/etherswitch/e6000sw/e6000swreg.h @@ -45,6 +45,7 @@ struct atu_opt { #define MV88E6341 0x3410 #define MV88E6352 0x3520 #define MV88E6172 0x1720 +#define MV88E6171 0x1710 #define MV88E6176 0x1760 #define MV88E6190 0x1900 #define MV88E6190X 0x0a00 diff --git a/sys/dev/evdev/evdev_utils.c b/sys/dev/evdev/evdev_utils.c index a075a9be9bb7..d7b7b790dc2c 100644 --- a/sys/dev/evdev/evdev_utils.c +++ b/sys/dev/evdev/evdev_utils.c @@ -92,8 +92,8 @@ static uint16_t evdev_usb_scancodes[256] = { NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, /* 0xc0 - 0xdf */ - NONE, NONE, NONE, NONE, - NONE, NONE, NONE, NONE, + KEY_BRIGHTNESSDOWN, KEY_BRIGHTNESSUP, KEY_SCALE, KEY_DASHBOARD, + KEY_KBDILLUMDOWN, KEY_KBDILLUMUP, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, @@ -108,7 +108,12 @@ static uint16_t evdev_usb_scancodes[256] = { KEY_WWW, KEY_BACK, KEY_FORWARD, KEY_STOP, KEY_FIND, KEY_SCROLLUP, KEY_SCROLLDOWN, KEY_EDIT, KEY_SLEEP, KEY_COFFEE, KEY_REFRESH, KEY_CALC, - NONE, NONE, NONE, NONE, + /* + * last item maps to APPLE_FN_KEY in hkbd.c. using KEY_WAKEUP instead + * of KEY_FN as evdev translates the latter to too high of a code for + * xkb to parse. + */ + NONE, NONE, NONE, KEY_WAKEUP, }; diff --git a/sys/dev/evdev/input-event-codes.h b/sys/dev/evdev/input-event-codes.h index 81c88ec86b9b..4f1d0f96e400 100644 --- a/sys/dev/evdev/input-event-codes.h +++ b/sys/dev/evdev/input-event-codes.h @@ -28,26 +28,18 @@ #ifndef _EVDEV_INPUT_EVENT_CODES_H #define _EVDEV_INPUT_EVENT_CODES_H -/* - * Device properties and quirks - */ - -#define INPUT_PROP_POINTER 0x00 /* needs a pointer */ -#define INPUT_PROP_DIRECT 0x01 /* direct input devices */ -#define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */ -#define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */ -#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */ -#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */ -#define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */ -#define INPUT_PROP_PRESSUREPAD 0x07 /* pressure triggers clicks */ +#define INPUT_PROP_POINTER 0x00 +#define INPUT_PROP_DIRECT 0x01 +#define INPUT_PROP_BUTTONPAD 0x02 +#define INPUT_PROP_SEMI_MT 0x03 +#define INPUT_PROP_TOPBUTTONPAD 0x04 +#define INPUT_PROP_POINTING_STICK 0x05 +#define INPUT_PROP_ACCELEROMETER 0x06 +#define INPUT_PROP_PRESSUREPAD 0x07 #define INPUT_PROP_MAX 0x1f #define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) -/* - * Event types - */ - #define EV_SYN 0x00 #define EV_KEY 0x01 #define EV_REL 0x02 @@ -63,10 +55,6 @@ #define EV_MAX 0x1f #define EV_CNT (EV_MAX+1) -/* - * Synchronization events. - */ - #define SYN_REPORT 0 #define SYN_CONFIG 1 #define SYN_MT_REPORT 2 @@ -74,17 +62,6 @@ #define SYN_MAX 0xf #define SYN_CNT (SYN_MAX+1) -/* - * Keys and buttons - * - * Most of the keys/buttons are modeled after USB HUT 1.12 - * (see http://www.usb.org/developers/hidpage). - * Abbreviations in the comments: - * AC - Application Control - * AL - Application Launch Button - * SC - System Control - */ - #define KEY_RESERVED 0 #define KEY_ESC 1 #define KEY_1 2 @@ -201,11 +178,11 @@ #define KEY_MUTE 113 #define KEY_VOLUMEDOWN 114 #define KEY_VOLUMEUP 115 -#define KEY_POWER 116 /* SC System Power Down */ +#define KEY_POWER 116 #define KEY_KPEQUAL 117 #define KEY_KPPLUSMINUS 118 #define KEY_PAUSE 119 -#define KEY_SCALE 120 /* AL Compiz Scale (Expose) */ +#define KEY_SCALE 120 #define KEY_KPCOMMA 121 #define KEY_HANGEUL 122 @@ -216,40 +193,40 @@ #define KEY_RIGHTMETA 126 #define KEY_COMPOSE 127 -#define KEY_STOP 128 /* AC Stop */ +#define KEY_STOP 128 #define KEY_AGAIN 129 -#define KEY_PROPS 130 /* AC Properties */ -#define KEY_UNDO 131 /* AC Undo */ +#define KEY_PROPS 130 +#define KEY_UNDO 131 #define KEY_FRONT 132 -#define KEY_COPY 133 /* AC Copy */ -#define KEY_OPEN 134 /* AC Open */ -#define KEY_PASTE 135 /* AC Paste */ -#define KEY_FIND 136 /* AC Search */ -#define KEY_CUT 137 /* AC Cut */ -#define KEY_HELP 138 /* AL Integrated Help Center */ -#define KEY_MENU 139 /* Menu (show menu) */ -#define KEY_CALC 140 /* AL Calculator */ +#define KEY_COPY 133 +#define KEY_OPEN 134 +#define KEY_PASTE 135 +#define KEY_FIND 136 +#define KEY_CUT 137 +#define KEY_HELP 138 +#define KEY_MENU 139 +#define KEY_CALC 140 #define KEY_SETUP 141 -#define KEY_SLEEP 142 /* SC System Sleep */ -#define KEY_WAKEUP 143 /* System Wake Up */ -#define KEY_FILE 144 /* AL Local Machine Browser */ +#define KEY_SLEEP 142 +#define KEY_WAKEUP 143 +#define KEY_FILE 144 #define KEY_SENDFILE 145 #define KEY_DELETEFILE 146 #define KEY_XFER 147 #define KEY_PROG1 148 #define KEY_PROG2 149 -#define KEY_WWW 150 /* AL Internet Browser */ +#define KEY_WWW 150 #define KEY_MSDOS 151 -#define KEY_COFFEE 152 /* AL Terminal Lock/Screensaver */ +#define KEY_COFFEE 152 #define KEY_SCREENLOCK KEY_COFFEE -#define KEY_ROTATE_DISPLAY 153 /* Display orientation for e.g. tablets */ +#define KEY_ROTATE_DISPLAY 153 #define KEY_DIRECTION KEY_ROTATE_DISPLAY #define KEY_CYCLEWINDOWS 154 #define KEY_MAIL 155 -#define KEY_BOOKMARKS 156 /* AC Bookmarks */ +#define KEY_BOOKMARKS 156 #define KEY_COMPUTER 157 -#define KEY_BACK 158 /* AC Back */ -#define KEY_FORWARD 159 /* AC Forward */ +#define KEY_BACK 158 +#define KEY_FORWARD 159 #define KEY_CLOSECD 160 #define KEY_EJECTCD 161 #define KEY_EJECTCLOSECD 162 @@ -259,20 +236,20 @@ #define KEY_STOPCD 166 #define KEY_RECORD 167 #define KEY_REWIND 168 -#define KEY_PHONE 169 /* Media Select Telephone */ +#define KEY_PHONE 169 #define KEY_ISO 170 -#define KEY_CONFIG 171 /* AL Consumer Control Configuration */ -#define KEY_HOMEPAGE 172 /* AC Home */ -#define KEY_REFRESH 173 /* AC Refresh */ -#define KEY_EXIT 174 /* AC Exit */ +#define KEY_CONFIG 171 +#define KEY_HOMEPAGE 172 +#define KEY_REFRESH 173 +#define KEY_EXIT 174 #define KEY_MOVE 175 #define KEY_EDIT 176 #define KEY_SCROLLUP 177 #define KEY_SCROLLDOWN 178 #define KEY_KPLEFTPAREN 179 #define KEY_KPRIGHTPAREN 180 -#define KEY_NEW 181 /* AC New */ -#define KEY_REDO 182 /* AC Redo/Repeat */ +#define KEY_NEW 181 +#define KEY_REDO 182 #define KEY_F13 183 #define KEY_F14 184 @@ -291,14 +268,14 @@ #define KEY_PAUSECD 201 #define KEY_PROG3 202 #define KEY_PROG4 203 -#define KEY_ALL_APPLICATIONS 204 /* AC Desktop Show All Applications */ +#define KEY_ALL_APPLICATIONS 204 #define KEY_DASHBOARD KEY_ALL_APPLICATIONS #define KEY_SUSPEND 205 -#define KEY_CLOSE 206 /* AC Close */ +#define KEY_CLOSE 206 #define KEY_PLAY 207 #define KEY_FASTFORWARD 208 #define KEY_BASSBOOST 209 -#define KEY_PRINT 210 /* AC Print */ +#define KEY_PRINT 210 #define KEY_HP 211 #define KEY_CAMERA 212 #define KEY_SOUND 213 @@ -307,25 +284,24 @@ #define KEY_CHAT 216 #define KEY_SEARCH 217 #define KEY_CONNECT 218 -#define KEY_FINANCE 219 /* AL Checkbook/Finance */ +#define KEY_FINANCE 219 #define KEY_SPORT 220 #define KEY_SHOP 221 #define KEY_ALTERASE 222 -#define KEY_CANCEL 223 /* AC Cancel */ +#define KEY_CANCEL 223 #define KEY_BRIGHTNESSDOWN 224 #define KEY_BRIGHTNESSUP 225 #define KEY_MEDIA 226 -#define KEY_SWITCHVIDEOMODE 227 /* Cycle between available video - outputs (Monitor/LCD/TV-out/etc) */ +#define KEY_SWITCHVIDEOMODE 227 #define KEY_KBDILLUMTOGGLE 228 #define KEY_KBDILLUMDOWN 229 #define KEY_KBDILLUMUP 230 -#define KEY_SEND 231 /* AC Send */ -#define KEY_REPLY 232 /* AC Reply */ -#define KEY_FORWARDMAIL 233 /* AC Forward Msg */ -#define KEY_SAVE 234 /* AC Save */ +#define KEY_SEND 231 +#define KEY_REPLY 232 +#define KEY_FORWARDMAIL 233 +#define KEY_SAVE 234 #define KEY_DOCUMENTS 235 #define KEY_BATTERY 236 @@ -336,22 +312,18 @@ #define KEY_UNKNOWN 240 -#define KEY_VIDEO_NEXT 241 /* drive next video source */ -#define KEY_VIDEO_PREV 242 /* drive previous video source */ -#define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */ -#define KEY_BRIGHTNESS_AUTO 244 /* Set Auto Brightness: manual - brightness control is off, - rely on ambient */ +#define KEY_VIDEO_NEXT 241 +#define KEY_VIDEO_PREV 242 +#define KEY_BRIGHTNESS_CYCLE 243 +#define KEY_BRIGHTNESS_AUTO 244 #define KEY_BRIGHTNESS_ZERO KEY_BRIGHTNESS_AUTO -#define KEY_DISPLAY_OFF 245 /* display device to off state */ +#define KEY_DISPLAY_OFF 245 -#define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */ +#define KEY_WWAN 246 #define KEY_WIMAX KEY_WWAN -#define KEY_RFKILL 247 /* Key that controls all radios */ - -#define KEY_MICMUTE 248 /* Mute / unmute the microphone */ +#define KEY_RFKILL 247 -/* Code 255 is reserved for special needs of AT keyboard driver */ +#define KEY_MICMUTE 248 #define BTN_MISC 0x100 #define BTN_0 0x100 @@ -420,14 +392,14 @@ #define BTN_TOOL_FINGER 0x145 #define BTN_TOOL_MOUSE 0x146 #define BTN_TOOL_LENS 0x147 -#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */ +#define BTN_TOOL_QUINTTAP 0x148 #define BTN_STYLUS3 0x149 #define BTN_TOUCH 0x14a #define BTN_STYLUS 0x14b #define BTN_STYLUS2 0x14c #define BTN_TOOL_DOUBLETAP 0x14d #define BTN_TOOL_TRIPLETAP 0x14e -#define BTN_TOOL_QUADTAP 0x14f /* Four fingers on trackpad */ +#define BTN_TOOL_QUADTAP 0x14f #define BTN_WHEEL 0x150 #define BTN_GEAR_DOWN 0x150 @@ -439,56 +411,56 @@ #define KEY_CLEAR 0x163 #define KEY_POWER2 0x164 #define KEY_OPTION 0x165 -#define KEY_INFO 0x166 /* AL OEM Features/Tips/Tutorial */ +#define KEY_INFO 0x166 #define KEY_TIME 0x167 #define KEY_VENDOR 0x168 #define KEY_ARCHIVE 0x169 -#define KEY_PROGRAM 0x16a /* Media Select Program Guide */ +#define KEY_PROGRAM 0x16a #define KEY_CHANNEL 0x16b #define KEY_FAVORITES 0x16c #define KEY_EPG 0x16d -#define KEY_PVR 0x16e /* Media Select Home */ +#define KEY_PVR 0x16e #define KEY_MHP 0x16f #define KEY_LANGUAGE 0x170 #define KEY_TITLE 0x171 #define KEY_SUBTITLE 0x172 #define KEY_ANGLE 0x173 -#define KEY_FULL_SCREEN 0x174 /* AC View Toggle */ +#define KEY_FULL_SCREEN 0x174 #define KEY_ZOOM KEY_FULL_SCREEN #define KEY_MODE 0x175 #define KEY_KEYBOARD 0x176 -#define KEY_ASPECT_RATIO 0x177 /* HUTRR37: Aspect */ +#define KEY_ASPECT_RATIO 0x177 #define KEY_SCREEN KEY_ASPECT_RATIO -#define KEY_PC 0x178 /* Media Select Computer */ -#define KEY_TV 0x179 /* Media Select TV */ -#define KEY_TV2 0x17a /* Media Select Cable */ -#define KEY_VCR 0x17b /* Media Select VCR */ -#define KEY_VCR2 0x17c /* VCR Plus */ -#define KEY_SAT 0x17d /* Media Select Satellite */ +#define KEY_PC 0x178 +#define KEY_TV 0x179 +#define KEY_TV2 0x17a +#define KEY_VCR 0x17b +#define KEY_VCR2 0x17c +#define KEY_SAT 0x17d #define KEY_SAT2 0x17e -#define KEY_CD 0x17f /* Media Select CD */ -#define KEY_TAPE 0x180 /* Media Select Tape */ +#define KEY_CD 0x17f +#define KEY_TAPE 0x180 #define KEY_RADIO 0x181 -#define KEY_TUNER 0x182 /* Media Select Tuner */ +#define KEY_TUNER 0x182 #define KEY_PLAYER 0x183 #define KEY_TEXT 0x184 -#define KEY_DVD 0x185 /* Media Select DVD */ +#define KEY_DVD 0x185 #define KEY_AUX 0x186 #define KEY_MP3 0x187 -#define KEY_AUDIO 0x188 /* AL Audio Browser */ -#define KEY_VIDEO 0x189 /* AL Movie Browser */ +#define KEY_AUDIO 0x188 +#define KEY_VIDEO 0x189 #define KEY_DIRECTORY 0x18a #define KEY_LIST 0x18b -#define KEY_MEMO 0x18c /* Media Select Messages */ +#define KEY_MEMO 0x18c #define KEY_CALENDAR 0x18d #define KEY_RED 0x18e #define KEY_GREEN 0x18f #define KEY_YELLOW 0x190 #define KEY_BLUE 0x191 -#define KEY_CHANNELUP 0x192 /* Channel Increment */ -#define KEY_CHANNELDOWN 0x193 /* Channel Decrement */ +#define KEY_CHANNELUP 0x192 +#define KEY_CHANNELDOWN 0x193 #define KEY_FIRST 0x194 -#define KEY_LAST 0x195 /* Recall Last */ +#define KEY_LAST 0x195 #define KEY_AB 0x196 #define KEY_NEXT 0x197 #define KEY_RESTART 0x198 @@ -499,40 +471,40 @@ #define KEY_DIGITS 0x19d #define KEY_TEEN 0x19e #define KEY_TWEN 0x19f -#define KEY_VIDEOPHONE 0x1a0 /* Media Select Video Phone */ -#define KEY_GAMES 0x1a1 /* Media Select Games */ -#define KEY_ZOOMIN 0x1a2 /* AC Zoom In */ -#define KEY_ZOOMOUT 0x1a3 /* AC Zoom Out */ -#define KEY_ZOOMRESET 0x1a4 /* AC Zoom */ -#define KEY_WORDPROCESSOR 0x1a5 /* AL Word Processor */ -#define KEY_EDITOR 0x1a6 /* AL Text Editor */ -#define KEY_SPREADSHEET 0x1a7 /* AL Spreadsheet */ -#define KEY_GRAPHICSEDITOR 0x1a8 /* AL Graphics Editor */ -#define KEY_PRESENTATION 0x1a9 /* AL Presentation App */ -#define KEY_DATABASE 0x1aa /* AL Database App */ -#define KEY_NEWS 0x1ab /* AL Newsreader */ -#define KEY_VOICEMAIL 0x1ac /* AL Voicemail */ -#define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */ -#define KEY_MESSENGER 0x1ae /* AL Instant Messaging */ -#define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */ +#define KEY_VIDEOPHONE 0x1a0 +#define KEY_GAMES 0x1a1 +#define KEY_ZOOMIN 0x1a2 +#define KEY_ZOOMOUT 0x1a3 +#define KEY_ZOOMRESET 0x1a4 +#define KEY_WORDPROCESSOR 0x1a5 +#define KEY_EDITOR 0x1a6 +#define KEY_SPREADSHEET 0x1a7 +#define KEY_GRAPHICSEDITOR 0x1a8 +#define KEY_PRESENTATION 0x1a9 +#define KEY_DATABASE 0x1aa +#define KEY_NEWS 0x1ab +#define KEY_VOICEMAIL 0x1ac +#define KEY_ADDRESSBOOK 0x1ad +#define KEY_MESSENGER 0x1ae +#define KEY_DISPLAYTOGGLE 0x1af #define KEY_BRIGHTNESS_TOGGLE KEY_DISPLAYTOGGLE -#define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */ -#define KEY_LOGOFF 0x1b1 /* AL Logoff */ +#define KEY_SPELLCHECK 0x1b0 +#define KEY_LOGOFF 0x1b1 #define KEY_DOLLAR 0x1b2 #define KEY_EURO 0x1b3 -#define KEY_FRAMEBACK 0x1b4 /* Consumer - transport controls */ +#define KEY_FRAMEBACK 0x1b4 #define KEY_FRAMEFORWARD 0x1b5 -#define KEY_CONTEXT_MENU 0x1b6 /* GenDesc - system context menu */ -#define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */ -#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ -#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ -#define KEY_IMAGES 0x1ba /* AL Image Browser */ -#define KEY_NOTIFICATION_CENTER 0x1bc /* Show/hide the notification center */ -#define KEY_PICKUP_PHONE 0x1bd /* Answer incoming call */ -#define KEY_HANGUP_PHONE 0x1be /* Decline incoming call */ -#define KEY_LINK_PHONE 0x1bf /* AL Phone Syncing */ +#define KEY_CONTEXT_MENU 0x1b6 +#define KEY_MEDIA_REPEAT 0x1b7 +#define KEY_10CHANNELSUP 0x1b8 +#define KEY_10CHANNELSDOWN 0x1b9 +#define KEY_IMAGES 0x1ba +#define KEY_NOTIFICATION_CENTER 0x1bc +#define KEY_PICKUP_PHONE 0x1bd +#define KEY_HANGUP_PHONE 0x1be +#define KEY_LINK_PHONE 0x1bf #define KEY_DEL_EOL 0x1c0 #define KEY_DEL_EOS 0x1c1 @@ -573,8 +545,8 @@ #define KEY_BRL_DOT9 0x1f9 #define KEY_BRL_DOT10 0x1fa -#define KEY_NUMERIC_0 0x200 /* used by phones, remote controls, */ -#define KEY_NUMERIC_1 0x201 /* and other keypads */ +#define KEY_NUMERIC_0 0x200 +#define KEY_NUMERIC_1 0x201 #define KEY_NUMERIC_2 0x202 #define KEY_NUMERIC_3 0x203 #define KEY_NUMERIC_4 0x204 @@ -585,15 +557,14 @@ #define KEY_NUMERIC_9 0x209 #define KEY_NUMERIC_STAR 0x20a #define KEY_NUMERIC_POUND 0x20b -#define KEY_NUMERIC_A 0x20c /* Phone key A - HUT Telephony 0xb9 */ +#define KEY_NUMERIC_A 0x20c #define KEY_NUMERIC_B 0x20d #define KEY_NUMERIC_C 0x20e #define KEY_NUMERIC_D 0x20f - #define KEY_CAMERA_FOCUS 0x210 -#define KEY_WPS_BUTTON 0x211 /* WiFi Protected Setup key */ +#define KEY_WPS_BUTTON 0x211 -#define KEY_TOUCHPAD_TOGGLE 0x212 /* Request switch touchpad on or off */ +#define KEY_TOUCHPAD_TOGGLE 0x212 #define KEY_TOUCHPAD_ON 0x213 #define KEY_TOUCHPAD_OFF 0x214 @@ -603,11 +574,10 @@ #define KEY_CAMERA_DOWN 0x218 #define KEY_CAMERA_LEFT 0x219 #define KEY_CAMERA_RIGHT 0x21a - #define KEY_ATTENDANT_ON 0x21b #define KEY_ATTENDANT_OFF 0x21c -#define KEY_ATTENDANT_TOGGLE 0x21d /* Attendant call on or off */ -#define KEY_LIGHTS_TOGGLE 0x21e /* Reading light on or off */ +#define KEY_ATTENDANT_TOGGLE 0x21d +#define KEY_LIGHTS_TOGGLE 0x21e #define BTN_DPAD_UP 0x220 #define BTN_DPAD_DOWN 0x221 @@ -619,94 +589,69 @@ #define BTN_GRIPL2 0x226 #define BTN_GRIPR2 0x227 -#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */ -#define KEY_ROTATE_LOCK_TOGGLE 0x231 /* Display rotation lock */ -#define KEY_REFRESH_RATE_TOGGLE 0x232 /* Display refresh rate toggle */ - -#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */ -#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */ -#define KEY_JOURNAL 0x242 /* AL Log/Journal/Timecard */ -#define KEY_CONTROLPANEL 0x243 /* AL Control Panel */ -#define KEY_APPSELECT 0x244 /* AL Select Task/Application */ -#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */ -#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ -#define KEY_ASSISTANT 0x247 /* AL Context-aware desktop assistant */ -#define KEY_KBD_LAYOUT_NEXT 0x248 /* AC Next Keyboard Layout Select */ -#define KEY_EMOJI_PICKER 0x249 /* Show/hide emoji picker (HUTRR101) */ -#define KEY_DICTATE 0x24a /* Start or Stop Voice Dictation Session (HUTRR99) */ -#define KEY_CAMERA_ACCESS_ENABLE 0x24b /* Enables programmatic access to camera devices. (HUTRR72) */ -#define KEY_CAMERA_ACCESS_DISABLE 0x24c /* Disables programmatic access to camera devices. (HUTRR72) */ -#define KEY_CAMERA_ACCESS_TOGGLE 0x24d /* Toggles the current state of the camera access control. (HUTRR72) */ -#define KEY_ACCESSIBILITY 0x24e /* Toggles the system bound accessibility UI/command (HUTRR116) */ -#define KEY_DO_NOT_DISTURB 0x24f /* Toggles the system-wide "Do Not Disturb" control (HUTRR94)*/ - -#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ -#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ - -/* - * Keycodes for hotkeys toggling the electronic privacy screen found on some - * laptops on/off. Note when the embedded-controller turns on/off the eprivacy - * screen itself then the state should be reported through drm connecter props: - * https://www.kernel.org/doc/html/latest/gpu/drm-kms.html#standard-connector-properties - * Except when implementing the drm connecter properties API is not possible - * because e.g. the firmware does not allow querying the presence and/or status - * of the eprivacy screen at boot. - */ +#define KEY_ALS_TOGGLE 0x230 +#define KEY_ROTATE_LOCK_TOGGLE 0x231 +#define KEY_REFRESH_RATE_TOGGLE 0x232 + +#define KEY_BUTTONCONFIG 0x240 +#define KEY_TASKMANAGER 0x241 +#define KEY_JOURNAL 0x242 +#define KEY_CONTROLPANEL 0x243 +#define KEY_APPSELECT 0x244 +#define KEY_SCREENSAVER 0x245 +#define KEY_VOICECOMMAND 0x246 +#define KEY_ASSISTANT 0x247 +#define KEY_KBD_LAYOUT_NEXT 0x248 +#define KEY_EMOJI_PICKER 0x249 +#define KEY_DICTATE 0x24a +#define KEY_CAMERA_ACCESS_ENABLE 0x24b +#define KEY_CAMERA_ACCESS_DISABLE 0x24c +#define KEY_CAMERA_ACCESS_TOGGLE 0x24d +#define KEY_ACCESSIBILITY 0x24e +#define KEY_DO_NOT_DISTURB 0x24f + +#define KEY_BRIGHTNESS_MIN 0x250 +#define KEY_BRIGHTNESS_MAX 0x251 + #define KEY_EPRIVACY_SCREEN_ON 0x252 #define KEY_EPRIVACY_SCREEN_OFF 0x253 #define KEY_KBDINPUTASSIST_PREV 0x260 #define KEY_KBDINPUTASSIST_NEXT 0x261 -#define KEY_KBDINPUTASSIST_PREVGROUP 0x262 -#define KEY_KBDINPUTASSIST_NEXTGROUP 0x263 -#define KEY_KBDINPUTASSIST_ACCEPT 0x264 -#define KEY_KBDINPUTASSIST_CANCEL 0x265 +#define KEY_KBDINPUTASSIST_PREVGROUP 0x262 +#define KEY_KBDINPUTASSIST_NEXTGROUP 0x263 +#define KEY_KBDINPUTASSIST_ACCEPT 0x264 +#define KEY_KBDINPUTASSIST_CANCEL 0x265 -/* Diagonal movement keys */ #define KEY_RIGHT_UP 0x266 #define KEY_RIGHT_DOWN 0x267 #define KEY_LEFT_UP 0x268 #define KEY_LEFT_DOWN 0x269 -#define KEY_ROOT_MENU 0x26a /* Show Device's Root Menu */ -/* Show Top Menu of the Media (e.g. DVD) */ +#define KEY_ROOT_MENU 0x26a #define KEY_MEDIA_TOP_MENU 0x26b #define KEY_NUMERIC_11 0x26c #define KEY_NUMERIC_12 0x26d -/* - * Toggle Audio Description: refers to an audio service that helps blind and - * visually impaired consumers understand the action in a program. Note: in - * some countries this is referred to as "Video Description". - */ #define KEY_AUDIO_DESC 0x26e #define KEY_3D_MODE 0x26f #define KEY_NEXT_FAVORITE 0x270 #define KEY_STOP_RECORD 0x271 #define KEY_PAUSE_RECORD 0x272 -#define KEY_VOD 0x273 /* Video on Demand */ +#define KEY_VOD 0x273 #define KEY_UNMUTE 0x274 #define KEY_FASTREVERSE 0x275 #define KEY_SLOWREVERSE 0x276 -/* - * Control a data application associated with the currently viewed channel, - * e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.) - */ #define KEY_DATA 0x277 #define KEY_ONSCREEN_KEYBOARD 0x278 -/* Electronic privacy screen control */ #define KEY_PRIVACY_SCREEN_TOGGLE 0x279 -/* Select an area of screen to be copied */ #define KEY_SELECTIVE_SCREENSHOT 0x27a -/* Move the focus to the next or previous user controllable element within a UI container */ #define KEY_NEXT_ELEMENT 0x27b #define KEY_PREVIOUS_ELEMENT 0x27c -/* Toggle Autopilot engagement */ #define KEY_AUTOPILOT_ENGAGE_TOGGLE 0x27d -/* Shortcut Keys */ #define KEY_MARK_WAYPOINT 0x27e #define KEY_SOS 0x27f #define KEY_NAV_CHART 0x280 @@ -720,21 +665,6 @@ #define KEY_NAV_INFO 0x288 #define KEY_BRIGHTNESS_MENU 0x289 -/* - * Some keyboards have keys which do not have a defined meaning, these keys - * are intended to be programmed / bound to macros by the user. For most - * keyboards with these macro-keys the key-sequence to inject, or action to - * take, is all handled by software on the host side. So from the kernel's - * point of view these are just normal keys. - * - * The KEY_MACRO# codes below are intended for such keys, which may be labeled - * e.g. G1-G18, or S1 - S30. The KEY_MACRO# codes MUST NOT be used for keys - * where the marking on the key does indicate a defined meaning / purpose. - * - * The KEY_MACRO# codes MUST also NOT be used as fallback for when no existing - * KEY_FOO define matches the marking / purpose. In this case a new KEY_FOO - * define MUST be added. - */ #define KEY_MACRO1 0x290 #define KEY_MACRO2 0x291 #define KEY_MACRO3 0x292 @@ -766,16 +696,6 @@ #define KEY_MACRO29 0x2ac #define KEY_MACRO30 0x2ad -/* - * Some keyboards with the macro-keys described above have some extra keys - * for controlling the host-side software responsible for the macro handling: - * -A macro recording start/stop key. Note that not all keyboards which emit - * KEY_MACRO_RECORD_START will also emit KEY_MACRO_RECORD_STOP if - * KEY_MACRO_RECORD_STOP is not advertised, then KEY_MACRO_RECORD_START - * should be interpreted as a recording start/stop toggle; - * -Keys for switching between different macro (pre)sets, either a key for - * cycling through the configured presets or keys to directly select a preset. - */ #define KEY_MACRO_RECORD_START 0x2b0 #define KEY_MACRO_RECORD_STOP 0x2b1 #define KEY_MACRO_PRESET_CYCLE 0x2b2 @@ -783,19 +703,12 @@ #define KEY_MACRO_PRESET2 0x2b4 #define KEY_MACRO_PRESET3 0x2b5 -/* - * Some keyboards have a buildin LCD panel where the contents are controlled - * by the host. Often these have a number of keys directly below the LCD - * intended for controlling a menu shown on the LCD. These keys often don't - * have any labeling so we just name them KEY_KBD_LCD_MENU# - */ #define KEY_KBD_LCD_MENU1 0x2b8 #define KEY_KBD_LCD_MENU2 0x2b9 #define KEY_KBD_LCD_MENU3 0x2ba #define KEY_KBD_LCD_MENU4 0x2bb #define KEY_KBD_LCD_MENU5 0x2bc -/* Performance Boost key (Alienware)/G-Mode key (Dell) */ #define KEY_PERFORMANCE 0x2bd #define BTN_TRIGGER_HAPPY 0x2c0 @@ -840,15 +753,10 @@ #define BTN_TRIGGER_HAPPY39 0x2e6 #define BTN_TRIGGER_HAPPY40 0x2e7 -/* We avoid low common keys in module aliases so they don't get huge. */ #define KEY_MIN_INTERESTING KEY_MUTE #define KEY_MAX 0x2ff #define KEY_CNT (KEY_MAX+1) -/* - * Relative axes - */ - #define REL_X 0x00 #define REL_Y 0x01 #define REL_Z 0x02 @@ -859,23 +767,12 @@ #define REL_DIAL 0x07 #define REL_WHEEL 0x08 #define REL_MISC 0x09 -/* - * 0x0a is reserved and should not be used in input drivers. - * It was used by HID as REL_MISC+1 and userspace needs to detect if - * the next REL_* event is correct or is just REL_MISC + n. - * We define here REL_RESERVED so userspace can rely on it and detect - * the situation described above. - */ #define REL_RESERVED 0x0a #define REL_WHEEL_HI_RES 0x0b #define REL_HWHEEL_HI_RES 0x0c #define REL_MAX 0x0f #define REL_CNT (REL_MAX+1) -/* - * Absolute axes - */ - #define ABS_X 0x00 #define ABS_Y 0x01 #define ABS_Z 0x02 @@ -906,65 +803,49 @@ #define ABS_MISC 0x28 -/* - * 0x2e is reserved and should not be used in input drivers. - * It was used by HID as ABS_MISC+6 and userspace needs to detect if - * the next ABS_* event is correct or is just ABS_MISC + n. - * We define here ABS_RESERVED so userspace can rely on it and detect - * the situation described above. - */ #define ABS_RESERVED 0x2e -#define ABS_MT_SLOT 0x2f /* MT slot being modified */ -#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */ -#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */ -#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */ -#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */ -#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */ -#define ABS_MT_POSITION_X 0x35 /* Center X touch position */ -#define ABS_MT_POSITION_Y 0x36 /* Center Y touch position */ -#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */ -#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */ -#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */ -#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */ -#define ABS_MT_DISTANCE 0x3b /* Contact hover distance */ -#define ABS_MT_TOOL_X 0x3c /* Center X tool position */ -#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */ +#define ABS_MT_SLOT 0x2f +#define ABS_MT_TOUCH_MAJOR 0x30 +#define ABS_MT_TOUCH_MINOR 0x31 +#define ABS_MT_WIDTH_MAJOR 0x32 +#define ABS_MT_WIDTH_MINOR 0x33 +#define ABS_MT_ORIENTATION 0x34 +#define ABS_MT_POSITION_X 0x35 +#define ABS_MT_POSITION_Y 0x36 +#define ABS_MT_TOOL_TYPE 0x37 +#define ABS_MT_BLOB_ID 0x38 +#define ABS_MT_TRACKING_ID 0x39 +#define ABS_MT_PRESSURE 0x3a +#define ABS_MT_DISTANCE 0x3b +#define ABS_MT_TOOL_X 0x3c +#define ABS_MT_TOOL_Y 0x3d #define ABS_MAX 0x3f #define ABS_CNT (ABS_MAX+1) -/* - * Switch events - */ - -#define SW_LID 0x00 /* set = lid shut */ -#define SW_TABLET_MODE 0x01 /* set = tablet mode */ -#define SW_HEADPHONE_INSERT 0x02 /* set = inserted */ -#define SW_RFKILL_ALL 0x03 /* rfkill master switch, type "any" - set = radio enabled */ -#define SW_RADIO SW_RFKILL_ALL /* deprecated */ -#define SW_MICROPHONE_INSERT 0x04 /* set = inserted */ -#define SW_DOCK 0x05 /* set = plugged into dock */ -#define SW_LINEOUT_INSERT 0x06 /* set = inserted */ -#define SW_JACK_PHYSICAL_INSERT 0x07 /* set = mechanical switch set */ -#define SW_VIDEOOUT_INSERT 0x08 /* set = inserted */ -#define SW_CAMERA_LENS_COVER 0x09 /* set = lens covered */ -#define SW_KEYPAD_SLIDE 0x0a /* set = keypad slide out */ -#define SW_FRONT_PROXIMITY 0x0b /* set = front proximity sensor active */ -#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */ -#define SW_LINEIN_INSERT 0x0d /* set = inserted */ -#define SW_MUTE_DEVICE 0x0e /* set = device disabled */ -#define SW_PEN_INSERTED 0x0f /* set = pen inserted */ -#define SW_MACHINE_COVER 0x10 /* set = cover closed */ -#define SW_USB_INSERT 0x11 /* set = USB audio device connected */ +#define SW_LID 0x00 +#define SW_TABLET_MODE 0x01 +#define SW_HEADPHONE_INSERT 0x02 +#define SW_RFKILL_ALL 0x03 +#define SW_RADIO SW_RFKILL_ALL +#define SW_MICROPHONE_INSERT 0x04 +#define SW_DOCK 0x05 +#define SW_LINEOUT_INSERT 0x06 +#define SW_JACK_PHYSICAL_INSERT 0x07 +#define SW_VIDEOOUT_INSERT 0x08 +#define SW_CAMERA_LENS_COVER 0x09 +#define SW_KEYPAD_SLIDE 0x0a +#define SW_FRONT_PROXIMITY 0x0b +#define SW_ROTATE_LOCK 0x0c +#define SW_LINEIN_INSERT 0x0d +#define SW_MUTE_DEVICE 0x0e +#define SW_PEN_INSERTED 0x0f +#define SW_MACHINE_COVER 0x10 +#define SW_USB_INSERT 0x11 #define SW_MAX 0x11 #define SW_CNT (SW_MAX+1) -/* - * Misc events - */ - #define MSC_SERIAL 0x00 #define MSC_PULSELED 0x01 #define MSC_GESTURE 0x02 @@ -974,10 +855,6 @@ #define MSC_MAX 0x07 #define MSC_CNT (MSC_MAX+1) -/* - * LEDs - */ - #define LED_NUML 0x00 #define LED_CAPSL 0x01 #define LED_SCROLLL 0x02 @@ -992,19 +869,11 @@ #define LED_MAX 0x0f #define LED_CNT (LED_MAX+1) -/* - * Autorepeat values - */ - #define REP_DELAY 0x00 #define REP_PERIOD 0x01 #define REP_MAX 0x01 #define REP_CNT (REP_MAX+1) -/* - * Sounds - */ - #define SND_CLICK 0x00 #define SND_BELL 0x01 #define SND_TONE 0x02 diff --git a/sys/dev/fb/fbd.c b/sys/dev/fb/fbd.c index 6bae94aa6db6..f74c11bbf86b 100644 --- a/sys/dev/fb/fbd.c +++ b/sys/dev/fb/fbd.c @@ -348,7 +348,7 @@ static device_method_t fbd_methods[] = { DEVMETHOD(device_shutdown, bus_generic_shutdown), - { 0, 0 } + DEVMETHOD_END }; driver_t fbd_driver = { diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c index 58fcd1d5ea3d..2a1e426c24d0 100644 --- a/sys/dev/fdc/fdc.c +++ b/sys/dev/fdc/fdc.c @@ -2087,7 +2087,7 @@ static device_method_t fd_methods[] = { DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX */ DEVMETHOD(device_resume, bus_generic_resume), /* XXX */ - { 0, 0 } + DEVMETHOD_END }; static driver_t fd_driver = { diff --git a/sys/dev/fdc/fdc_isa.c b/sys/dev/fdc/fdc_isa.c index c1c8991e3e33..0216e1fda793 100644 --- a/sys/dev/fdc/fdc_isa.c +++ b/sys/dev/fdc/fdc_isa.c @@ -210,7 +210,7 @@ static device_method_t fdc_methods[] = { DEVMETHOD(bus_write_ivar, fdc_write_ivar), /* Our children never use any other bus interface methods. */ - { 0, 0 } + DEVMETHOD_END }; static driver_t fdc_driver = { diff --git a/sys/dev/fdc/fdcvar.h b/sys/dev/fdc/fdcvar.h index 881f6f9f898d..8b7081e0a6cc 100644 --- a/sys/dev/fdc/fdcvar.h +++ b/sys/dev/fdc/fdcvar.h @@ -69,7 +69,7 @@ struct fdc_data { }; enum fdc_device_ivars { - FDC_IVAR_FDUNIT, + FDC_IVAR_FDUNIT = BUS_IVARS_PRIVATE, FDC_IVAR_FDTYPE, }; diff --git a/sys/dev/fdt/fdt_static_dtb.S b/sys/dev/fdt/fdt_static_dtb.S index 6ff6e312197d..d657236479aa 100644 --- a/sys/dev/fdt/fdt_static_dtb.S +++ b/sys/dev/fdt/fdt_static_dtb.S @@ -28,6 +28,13 @@ #include "fdt_static_dtb.h" +#if defined(__aarch64__) +#include <sys/elf_common.h> +#include <machine/asm.h> + +GNU_PROPERTY_AARCH64_FEATURE_1_NOTE(GNU_PROPERTY_AARCH64_FEATURE_1_VAL) +#endif + .data .ascii "Device Tree Blob STARTS here" .global fdt_static_dtb diff --git a/sys/dev/fdt/simple_mfd.c b/sys/dev/fdt/simple_mfd.c index 1c642c6ca99c..66352e3f9409 100644 --- a/sys/dev/fdt/simple_mfd.c +++ b/sys/dev/fdt/simple_mfd.c @@ -207,7 +207,7 @@ simple_mfd_attach(device_t dev) if (ofw_bus_is_compatible(dev, "syscon")) { sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, - RF_ACTIVE); + RF_ACTIVE | RF_SHAREABLE); if (sc->mem_res == NULL) { device_printf(dev, "Cannot allocate memory resource\n"); diff --git a/sys/dev/firewire/if_fwe.c b/sys/dev/firewire/if_fwe.c index 44d3425799e9..4f8d0087e9ab 100644 --- a/sys/dev/firewire/if_fwe.c +++ b/sys/dev/firewire/if_fwe.c @@ -613,7 +613,7 @@ static device_method_t fwe_methods[] = { DEVMETHOD(device_probe, fwe_probe), DEVMETHOD(device_attach, fwe_attach), DEVMETHOD(device_detach, fwe_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t fwe_driver = { diff --git a/sys/dev/firewire/if_fwip.c b/sys/dev/firewire/if_fwip.c index 41143e2e59d4..42f0c6f53743 100644 --- a/sys/dev/firewire/if_fwip.c +++ b/sys/dev/firewire/if_fwip.c @@ -916,7 +916,7 @@ static device_method_t fwip_methods[] = { DEVMETHOD(device_probe, fwip_probe), DEVMETHOD(device_attach, fwip_attach), DEVMETHOD(device_detach, fwip_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t fwip_driver = { diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c index be1e60e45e75..9e76000f5fb6 100644 --- a/sys/dev/firewire/sbp.c +++ b/sys/dev/firewire/sbp.c @@ -2835,7 +2835,7 @@ static device_method_t sbp_methods[] = { DEVMETHOD(device_detach, sbp_detach), DEVMETHOD(device_shutdown, sbp_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t sbp_driver = { diff --git a/sys/dev/firewire/sbp_targ.c b/sys/dev/firewire/sbp_targ.c index 4efc16c1ee47..96a86c25b684 100644 --- a/sys/dev/firewire/sbp_targ.c +++ b/sys/dev/firewire/sbp_targ.c @@ -2036,7 +2036,7 @@ static device_method_t sbp_targ_methods[] = { DEVMETHOD(device_probe, sbp_targ_probe), DEVMETHOD(device_attach, sbp_targ_attach), DEVMETHOD(device_detach, sbp_targ_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t sbp_targ_driver = { diff --git a/sys/dev/flash/cqspi.c b/sys/dev/flash/cqspi.c index 4774d14add0e..9da1676bae5a 100644 --- a/sys/dev/flash/cqspi.c +++ b/sys/dev/flash/cqspi.c @@ -754,7 +754,7 @@ static device_method_t cqspi_methods[] = { DEVMETHOD(qspi_write, cqspi_write), DEVMETHOD(qspi_erase, cqspi_erase), - { 0, 0 } + DEVMETHOD_END }; DEFINE_CLASS_1(cqspi, cqspi_driver, cqspi_methods, diff --git a/sys/dev/flash/flexspi/flex_spi.c b/sys/dev/flash/flexspi/flex_spi.c index 44246f4b1c2d..12f431548d2a 100644 --- a/sys/dev/flash/flexspi/flex_spi.c +++ b/sys/dev/flash/flexspi/flex_spi.c @@ -970,7 +970,7 @@ static device_method_t flex_spi_methods[] = { DEVMETHOD(device_attach, flex_spi_attach), DEVMETHOD(device_detach, flex_spi_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t flex_spi_driver = { diff --git a/sys/dev/flash/mx25l.c b/sys/dev/flash/mx25l.c index 64e3e53d4291..c7c95716aaed 100644 --- a/sys/dev/flash/mx25l.c +++ b/sys/dev/flash/mx25l.c @@ -673,7 +673,7 @@ static device_method_t mx25l_methods[] = { DEVMETHOD(device_attach, mx25l_attach), DEVMETHOD(device_detach, mx25l_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t mx25l_driver = { diff --git a/sys/dev/flash/n25q.c b/sys/dev/flash/n25q.c index 95d005125930..495649357bf1 100644 --- a/sys/dev/flash/n25q.c +++ b/sys/dev/flash/n25q.c @@ -469,7 +469,7 @@ static device_method_t n25q_methods[] = { DEVMETHOD(device_attach, n25q_attach), DEVMETHOD(device_detach, n25q_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t n25q_driver = { diff --git a/sys/dev/flash/w25n.c b/sys/dev/flash/w25n.c index c106b99434ca..660c9b9d7d8e 100644 --- a/sys/dev/flash/w25n.c +++ b/sys/dev/flash/w25n.c @@ -586,7 +586,7 @@ static device_method_t w25n_methods[] = { DEVMETHOD(device_attach, w25n_attach), DEVMETHOD(device_detach, w25n_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t w25n_driver = { diff --git a/sys/dev/ftwd/ftwd.c b/sys/dev/ftwd/ftwd.c index 103c5f7c59d0..2f6f8892dc22 100644 --- a/sys/dev/ftwd/ftwd.c +++ b/sys/dev/ftwd/ftwd.c @@ -138,7 +138,7 @@ static device_method_t ftwd_methods[] = { DEVMETHOD(device_probe, ftwd_probe), DEVMETHOD(device_attach, ftwd_attach), DEVMETHOD(device_detach, ftwd_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ftwd_driver = { diff --git a/sys/dev/fxp/inphy.c b/sys/dev/fxp/inphy.c index 581849745724..a23f75cb39e2 100644 --- a/sys/dev/fxp/inphy.c +++ b/sys/dev/fxp/inphy.c @@ -63,7 +63,7 @@ static device_method_t inphy_methods[] = { DEVMETHOD(device_attach, inphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t inphy_driver = { diff --git a/sys/dev/glxiic/glxiic.c b/sys/dev/glxiic/glxiic.c index ef0a0e111339..bb2075e1d31c 100644 --- a/sys/dev/glxiic/glxiic.c +++ b/sys/dev/glxiic/glxiic.c @@ -266,7 +266,7 @@ static device_method_t glxiic_methods[] = { DEVMETHOD(iicbus_transfer, glxiic_transfer), DEVMETHOD(iicbus_callback, iicbus_null_callback), - { 0, 0 } + DEVMETHOD_END }; static driver_t glxiic_driver = { diff --git a/sys/dev/gpio/acpi_gpiobus.c b/sys/dev/gpio/acpi_gpiobus.c index 0c31f4fec16d..117c05799c08 100644 --- a/sys/dev/gpio/acpi_gpiobus.c +++ b/sys/dev/gpio/acpi_gpiobus.c @@ -401,7 +401,7 @@ acpi_gpiobus_read_ivar(device_t dev, device_t child, int which, struct acpi_gpiobus_ivar *devi = device_get_ivars(child); switch (which) { - case ACPI_GPIOBUS_IVAR_HANDLE: + case ACPI_IVAR_HANDLE: *result = (uintptr_t)devi->handle; break; default: diff --git a/sys/dev/gpio/acpi_gpiobusvar.h b/sys/dev/gpio/acpi_gpiobusvar.h index 288e8bd0f2af..ea4e7d44a217 100644 --- a/sys/dev/gpio/acpi_gpiobusvar.h +++ b/sys/dev/gpio/acpi_gpiobusvar.h @@ -28,21 +28,8 @@ #ifndef __ACPI_GPIOBUS_H__ #define __ACPI_GPIOBUS_H__ -#include <sys/bus.h> - #include <contrib/dev/acpica/include/acpi.h> -enum acpi_gpiobus_ivars { - ACPI_GPIOBUS_IVAR_HANDLE = 10600 -}; - -#define ACPI_GPIOBUS_ACCESSOR(var, ivar, type) \ - __BUS_ACCESSOR(acpi_gpiobus, var, ACPI_GPIOBUS, ivar, type) - -ACPI_GPIOBUS_ACCESSOR(handle, HANDLE, ACPI_HANDLE) - -#undef ACPI_GPIOBUS_ACCESSOR - uint32_t acpi_gpiobus_convflags(ACPI_RESOURCE_GPIO *); #endif /* __ACPI_GPIOBUS_H__ */ diff --git a/sys/dev/gpio/dwgpio/dwgpio.c b/sys/dev/gpio/dwgpio/dwgpio.c index 3908113d5fd4..c46b3ab38745 100644 --- a/sys/dev/gpio/dwgpio/dwgpio.c +++ b/sys/dev/gpio/dwgpio/dwgpio.c @@ -408,7 +408,7 @@ static device_method_t dwgpio_methods[] = { DEVMETHOD(gpio_pin_toggle, dwgpio_pin_toggle), DEVMETHOD(gpio_pin_setflags, dwgpio_pin_setflags), DEVMETHOD(gpio_pin_set, dwgpio_pin_set), - { 0, 0 } + DEVMETHOD_END }; static driver_t dwgpio_driver = { diff --git a/sys/dev/gpio/gpioaei.c b/sys/dev/gpio/gpioaei.c index 9a769a793e5a..3451d3120843 100644 --- a/sys/dev/gpio/gpioaei.c +++ b/sys/dev/gpio/gpioaei.c @@ -208,7 +208,7 @@ gpio_aei_attach(device_t dev) /* This is us. */ device_set_desc(dev, "ACPI Event Information Device"); - handle = acpi_gpiobus_get_handle(dev); + handle = acpi_get_handle(dev); status = AcpiGetParent(handle, &sc->dev_handle); if (ACPI_FAILURE(status)) { device_printf(dev, "Cannot get parent of %s\n", diff --git a/sys/dev/gpio/gpiobusvar.h b/sys/dev/gpio/gpiobusvar.h index 22a10ad2abc2..3d93e3d291b9 100644 --- a/sys/dev/gpio/gpiobusvar.h +++ b/sys/dev/gpio/gpiobusvar.h @@ -109,7 +109,7 @@ struct gpiobus_ivar }; enum gpiobus_ivars { - GPIOBUS_IVAR_NPINS = 10500, + GPIOBUS_IVAR_NPINS = BUS_IVARS_GPIOBUS, GPIOBUS_IVAR_PINS, }; diff --git a/sys/dev/gve/gve.h b/sys/dev/gve/gve.h index 64c2a0481817..1a163cfcbce0 100644 --- a/sys/dev/gve/gve.h +++ b/sys/dev/gve/gve.h @@ -166,7 +166,7 @@ struct gve_queue_page_list { uint32_t id; uint32_t num_dmas; uint32_t num_pages; - vm_offset_t kva; + char *kva; vm_page_t *pages; struct gve_dma_handle *dmas; }; @@ -350,7 +350,7 @@ struct gve_rx_ring { * uses it. */ struct gve_tx_fifo { - vm_offset_t base; /* address of base of FIFO */ + char *base; /* address of base of FIFO */ uint32_t size; /* total size */ volatile int available; /* how much space is still available */ uint32_t head; /* offset to write at */ diff --git a/sys/dev/gve/gve_qpl.c b/sys/dev/gve/gve_qpl.c index 0e7098dcd4a1..1f153d08c126 100644 --- a/sys/dev/gve/gve_qpl.c +++ b/sys/dev/gve/gve_qpl.c @@ -59,8 +59,8 @@ gve_free_qpl(struct gve_priv *priv, struct gve_queue_page_list *qpl) */ if (vm_page_unwire_noq(qpl->pages[i])) { if (!qpl->kva) { - pmap_qremove((vm_offset_t)qpl->dmas[i].cpu_addr, 1); - kva_free((vm_offset_t)qpl->dmas[i].cpu_addr, PAGE_SIZE); + pmap_qremove(qpl->dmas[i].cpu_addr, 1); + kva_free(qpl->dmas[i].cpu_addr, PAGE_SIZE); } vm_page_free(qpl->pages[i]); } @@ -104,7 +104,7 @@ gve_alloc_qpl(struct gve_priv *priv, uint32_t id, int npages, bool single_kva) qpl->pages = malloc(npages * sizeof(*qpl->pages), M_GVE_QPL, M_WAITOK | M_ZERO); - qpl->kva = 0; + qpl->kva = NULL; if (single_kva) { qpl->kva = kva_alloc(PAGE_SIZE * npages); if (!qpl->kva) { @@ -120,15 +120,15 @@ gve_alloc_qpl(struct gve_priv *priv, uint32_t id, int npages, bool single_kva) VM_ALLOC_ZERO); if (!single_kva) { - qpl->dmas[i].cpu_addr = (void *)kva_alloc(PAGE_SIZE); + qpl->dmas[i].cpu_addr = kva_alloc(PAGE_SIZE); if (!qpl->dmas[i].cpu_addr) { device_printf(priv->dev, "Failed to create kva for page %d in QPL %d", i, id); err = ENOMEM; goto abort; } - pmap_qenter((vm_offset_t)qpl->dmas[i].cpu_addr, &(qpl->pages[i]), 1); + pmap_qenter(qpl->dmas[i].cpu_addr, &(qpl->pages[i]), 1); } else - qpl->dmas[i].cpu_addr = (void *)(qpl->kva + (PAGE_SIZE * i)); + qpl->dmas[i].cpu_addr = qpl->kva + (PAGE_SIZE * i); qpl->num_pages++; @@ -244,7 +244,7 @@ void gve_mextadd_free(struct mbuf *mbuf) { vm_page_t page = (vm_page_t)mbuf->m_ext.ext_arg1; - vm_offset_t va = (vm_offset_t)mbuf->m_ext.ext_arg2; + void *va = mbuf->m_ext.ext_arg2; /* * Free the page only if this is the last ref. diff --git a/sys/dev/gve/gve_tx.c b/sys/dev/gve/gve_tx.c index 84e3a4c4eb9f..5e0611e1d6e4 100644 --- a/sys/dev/gve/gve_tx.c +++ b/sys/dev/gve/gve_tx.c @@ -735,7 +735,7 @@ gve_xmit(struct gve_tx_ring *tx, struct mbuf *mbuf) pkt_len); m_copydata(mbuf, 0, first_seg_len, - (char *)tx->fifo.base + info->iov[hdr_nfrags - 1].iov_offset); + tx->fifo.base + info->iov[hdr_nfrags - 1].iov_offset); gve_dma_sync_for_device(tx->com.qpl, info->iov[hdr_nfrags - 1].iov_offset, info->iov[hdr_nfrags - 1].iov_len); @@ -755,7 +755,7 @@ gve_xmit(struct gve_tx_ring *tx, struct mbuf *mbuf) info->iov[i].iov_offset, is_ipv6, l3_off, tso_mss); m_copydata(mbuf, copy_offset, info->iov[i].iov_len, - (char *)tx->fifo.base + info->iov[i].iov_offset); + tx->fifo.base + info->iov[i].iov_offset); gve_dma_sync_for_device(tx->com.qpl, info->iov[i].iov_offset, info->iov[i].iov_len); copy_offset += info->iov[i].iov_len; diff --git a/sys/dev/hid/appleir.c b/sys/dev/hid/appleir.c new file mode 100644 index 000000000000..956ad27f6d70 --- /dev/null +++ b/sys/dev/hid/appleir.c @@ -0,0 +1,440 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Abdelkader Boudih <freebsd@seuros.com> + */ + +/* + * Apple IR Remote Control Driver + * + * HID driver for Apple IR receivers (USB HID, vendor 0x05ac). + * Supports Apple Remote and generic IR remotes using NEC protocol. + * + * The Apple Remote protocol was reverse-engineered by James McKenzie and + * others; key codes and packet format constants are derived from that work + * and are factual descriptions of the hardware protocol, not copied code. + * Linux reference (GPL-2.0, no code copied): drivers/hid/hid-appleir.c + * + * Apple Remote Protocol (proprietary): + * Key down: [0x25][0x87][0xee][remote_id][key_code] + * Key repeat: [0x26][0x87][0xee][remote_id][key_code] + * Battery low: [0x25][0x87][0xe0][remote_id][0x00] + * Key decode: (byte4 >> 1) & 0x0F -> keymap[index] + * Two-packet: bit 6 of key_code (0x40) set -> store index, use on next keydown + * + * Generic IR Protocol (NEC-style): + * Format: [0x26][0x7f][0x80][code][~code] + * Checksum: code + ~code = 0xFF + * + * NO hardware key-up events -- synthesize via 125ms callout timer. + */ + +#include <sys/cdefs.h> + +#include "opt_hid.h" + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/callout.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/mutex.h> +#include <sys/sysctl.h> + +#include <dev/evdev/input.h> +#include <dev/evdev/evdev.h> + +#define HID_DEBUG_VAR appleir_debug +#include <dev/hid/hid.h> +#include <dev/hid/hidbus.h> +#include "usbdevs.h" + +#ifdef HID_DEBUG +static int appleir_debug = 0; + +static SYSCTL_NODE(_hw_hid, OID_AUTO, appleir, CTLFLAG_RW, 0, + "Apple IR Remote Control"); +SYSCTL_INT(_hw_hid_appleir, OID_AUTO, debug, CTLFLAG_RWTUN, + &appleir_debug, 0, "Debug level"); +#endif + +/* Protocol constants */ +#define APPLEIR_REPORT_LEN 5 +#define APPLEIR_KEY_MASK 0x0F +#define APPLEIR_TWO_PKT_FLAG 0x40 /* bit 6: two-packet command */ +#define APPLEIR_KEYUP_TICKS MAX(1, hz / 8) /* 125ms */ +#define APPLEIR_TWOPKT_TICKS MAX(1, hz / 4) /* 250ms */ + +/* Report type markers (byte 0) */ +#define APPLEIR_PKT_KEYDOWN 0x25 /* key down / battery low */ +#define APPLEIR_PKT_REPEAT 0x26 /* key repeat / NEC generic */ + +/* Apple Remote signature (bytes 1-2) */ +#define APPLEIR_SIG_HI 0x87 +#define APPLEIR_SIG_KEYLO 0xee /* normal key event */ +#define APPLEIR_SIG_BATTLO 0xe0 /* battery low event */ + +/* Generic IR NEC signature (bytes 1-2) */ +#define APPLEIR_NEC_HI 0x7f +#define APPLEIR_NEC_LO 0x80 +#define APPLEIR_NEC_CHECKSUM 0xFF /* code + ~code must equal this */ + +/* + * Apple IR keymap: 17 entries, index = (key_code >> 1) & 0x0F + * Based on Linux driver (hid-appleir.c) keymap. + */ +static const uint16_t appleir_keymap[] = { + KEY_RESERVED, /* 0x00 */ + KEY_MENU, /* 0x01 - menu */ + KEY_PLAYPAUSE, /* 0x02 - play/pause */ + KEY_FORWARD, /* 0x03 - >> */ + KEY_BACK, /* 0x04 - << */ + KEY_VOLUMEUP, /* 0x05 - + */ + KEY_VOLUMEDOWN, /* 0x06 - - */ + KEY_RESERVED, /* 0x07 */ + KEY_RESERVED, /* 0x08 */ + KEY_RESERVED, /* 0x09 */ + KEY_RESERVED, /* 0x0A */ + KEY_RESERVED, /* 0x0B */ + KEY_RESERVED, /* 0x0C */ + KEY_RESERVED, /* 0x0D */ + KEY_ENTER, /* 0x0E - middle button (two-packet) */ + KEY_PLAYPAUSE, /* 0x0F - play/pause (two-packet) */ + KEY_RESERVED, /* 0x10 - out of range guard */ +}; +#define APPLEIR_NKEYS (nitems(appleir_keymap)) + +/* + * Generic IR keymap (NEC protocol codes). + * Maps raw NEC codes to evdev KEY_* codes. + */ +struct generic_ir_map { + uint8_t code; /* NEC IR code */ + uint16_t key; /* evdev KEY_* */ +}; + +static const struct generic_ir_map generic_keymap[] = { + { 0xe1, KEY_VOLUMEUP }, + { 0xe9, KEY_VOLUMEDOWN }, + { 0xed, KEY_CHANNELUP }, + { 0xf3, KEY_CHANNELDOWN }, + { 0xf5, KEY_PLAYPAUSE }, + { 0xf9, KEY_POWER }, + { 0xfb, KEY_MUTE }, + { 0xfe, KEY_OK }, +}; +#define GENERIC_NKEYS (nitems(generic_keymap)) + +static uint16_t +generic_ir_lookup(uint8_t code) +{ + int i; + + for (i = 0; i < GENERIC_NKEYS; i++) { + if (generic_keymap[i].code == code) + return (generic_keymap[i].key); + } + return (KEY_RESERVED); +} + +struct appleir_softc { + device_t sc_dev; + struct mtx sc_mtx; /* protects below + callout */ + struct evdev_dev *sc_evdev; + struct callout sc_co; /* key-up timer */ + struct callout sc_twoco; /* two-packet timeout */ + uint16_t sc_current_key; /* evdev keycode (0=none) */ + int sc_prev_key_idx;/* two-packet state (0=none) */ + bool sc_batt_warned; +}; + + +/* + * Callout: synthesize key-up event (no hardware key-up from remote). + * Runs with sc_mtx held (callout_init_mtx). + */ +static void +appleir_keyup(void *arg) +{ + struct appleir_softc *sc = arg; + + mtx_assert(&sc->sc_mtx, MA_OWNED); + + if (sc->sc_current_key != 0) { + evdev_push_key(sc->sc_evdev, sc->sc_current_key, 0); + evdev_sync(sc->sc_evdev); + sc->sc_current_key = 0; + sc->sc_prev_key_idx = 0; + } +} + +static void +appleir_twopacket_timeout(void *arg) +{ + struct appleir_softc *sc = arg; + + mtx_assert(&sc->sc_mtx, MA_OWNED); + sc->sc_prev_key_idx = 0; +} + +/* + * Process 5-byte HID interrupt report. + * Called from hidbus interrupt context. + */ +static void +appleir_intr(void *context, void *data, hid_size_t len) +{ + struct appleir_softc *sc = context; + uint8_t *buf = data; + uint8_t report[APPLEIR_REPORT_LEN]; + int index; + uint16_t new_key; + + if (len != APPLEIR_REPORT_LEN) { + DPRINTFN(1, "bad report len: %zu\n", (size_t)len); + return; + } + + memcpy(report, buf, APPLEIR_REPORT_LEN); + + mtx_lock(&sc->sc_mtx); + + /* Battery low: [KEYDOWN][SIG_HI][SIG_BATTLO] -- log and ignore */ + if (report[0] == APPLEIR_PKT_KEYDOWN && + report[1] == APPLEIR_SIG_HI && report[2] == APPLEIR_SIG_BATTLO) { + if (!sc->sc_batt_warned) { + device_printf(sc->sc_dev, + "remote battery may be low\n"); + sc->sc_batt_warned = true; + } + goto done; + } + + /* Key down: [KEYDOWN][SIG_HI][SIG_KEYLO][remote_id][key_code] */ + if (report[0] == APPLEIR_PKT_KEYDOWN && + report[1] == APPLEIR_SIG_HI && report[2] == APPLEIR_SIG_KEYLO) { + /* Release previous key if held */ + if (sc->sc_current_key != 0) { + evdev_push_key(sc->sc_evdev, sc->sc_current_key, 0); + evdev_sync(sc->sc_evdev); + sc->sc_current_key = 0; + } + + if (sc->sc_prev_key_idx > 0) { + /* Second packet of a two-packet command */ + index = sc->sc_prev_key_idx; + sc->sc_prev_key_idx = 0; + callout_stop(&sc->sc_twoco); + } else if (report[4] & APPLEIR_TWO_PKT_FLAG) { + /* First packet of a two-packet command -- wait for next */ + sc->sc_prev_key_idx = (report[4] >> 1) & APPLEIR_KEY_MASK; + callout_reset(&sc->sc_twoco, APPLEIR_TWOPKT_TICKS, + appleir_twopacket_timeout, sc); + goto done; + } else { + index = (report[4] >> 1) & APPLEIR_KEY_MASK; + } + + new_key = (index < APPLEIR_NKEYS) ? + appleir_keymap[index] : KEY_RESERVED; + if (new_key != KEY_RESERVED) { + sc->sc_current_key = new_key; + evdev_push_key(sc->sc_evdev, new_key, 1); + evdev_sync(sc->sc_evdev); + callout_reset(&sc->sc_co, APPLEIR_KEYUP_TICKS, + appleir_keyup, sc); + } + goto done; + } + + /* Key repeat: [REPEAT][SIG_HI][SIG_KEYLO][remote_id][key_code] */ + if (report[0] == APPLEIR_PKT_REPEAT && + report[1] == APPLEIR_SIG_HI && report[2] == APPLEIR_SIG_KEYLO) { + uint16_t repeat_key; + int repeat_idx; + + if (sc->sc_prev_key_idx > 0) + goto done; + if (report[4] & APPLEIR_TWO_PKT_FLAG) + goto done; + + repeat_idx = (report[4] >> 1) & APPLEIR_KEY_MASK; + repeat_key = (repeat_idx < APPLEIR_NKEYS) ? + appleir_keymap[repeat_idx] : KEY_RESERVED; + if (repeat_key == KEY_RESERVED || + repeat_key != sc->sc_current_key) + goto done; + + evdev_push_key(sc->sc_evdev, repeat_key, 1); + evdev_sync(sc->sc_evdev); + callout_reset(&sc->sc_co, APPLEIR_KEYUP_TICKS, + appleir_keyup, sc); + goto done; + } + + /* Generic IR (NEC protocol): [REPEAT][NEC_HI][NEC_LO][code][~code] */ + if (report[0] == APPLEIR_PKT_REPEAT && + report[1] == APPLEIR_NEC_HI && report[2] == APPLEIR_NEC_LO) { + uint8_t code = report[3]; + uint8_t checksum = report[4]; + + sc->sc_prev_key_idx = 0; + callout_stop(&sc->sc_twoco); + + if ((uint8_t)(code + checksum) != APPLEIR_NEC_CHECKSUM) { + DPRINTFN(1, "generic IR: bad checksum %02x+%02x\n", + code, checksum); + goto done; + } + + new_key = generic_ir_lookup(code); + if (new_key == KEY_RESERVED) + goto done; + + if (sc->sc_current_key != new_key) { + if (sc->sc_current_key != 0) + evdev_push_key(sc->sc_evdev, + sc->sc_current_key, 0); + sc->sc_current_key = new_key; + evdev_push_key(sc->sc_evdev, new_key, 1); + evdev_sync(sc->sc_evdev); + } else { + evdev_push_key(sc->sc_evdev, new_key, 1); + evdev_sync(sc->sc_evdev); + } + callout_reset(&sc->sc_co, APPLEIR_KEYUP_TICKS, + appleir_keyup, sc); + goto done; + } + + DPRINTFN(1, "unknown report: %02x %02x %02x\n", + report[0], report[1], report[2]); + +done: + mtx_unlock(&sc->sc_mtx); +} + +/* Apple IR receiver device IDs */ +static const struct hid_device_id appleir_devs[] = { + { HID_BVP(BUS_USB, USB_VENDOR_APPLE, 0x8240) }, + { HID_BVP(BUS_USB, USB_VENDOR_APPLE, 0x8241) }, + { HID_BVP(BUS_USB, USB_VENDOR_APPLE, 0x8242) }, + { HID_BVP(BUS_USB, USB_VENDOR_APPLE, 0x8243) }, + { HID_BVP(BUS_USB, USB_VENDOR_APPLE, 0x1440) }, +}; + +static int +appleir_probe(device_t dev) +{ + int error; + + error = HIDBUS_LOOKUP_DRIVER_INFO(dev, appleir_devs); + if (error != 0) + return (error); + + /* Only attach to first top-level collection (TLC index 0) */ + if (hidbus_get_index(dev) != 0) + return (ENXIO); + + hidbus_set_desc(dev, "Apple IR Receiver"); + return (BUS_PROBE_DEFAULT); +} + +static int +appleir_attach(device_t dev) +{ + struct appleir_softc *sc = device_get_softc(dev); + const struct hid_device_info *hw; + int i, error; + + sc->sc_dev = dev; + hw = hid_get_device_info(dev); + sc->sc_current_key = 0; + sc->sc_prev_key_idx = 0; + sc->sc_batt_warned = false; + mtx_init(&sc->sc_mtx, "appleir", NULL, MTX_DEF); + callout_init_mtx(&sc->sc_co, &sc->sc_mtx, 0); + callout_init_mtx(&sc->sc_twoco, &sc->sc_mtx, 0); + + sc->sc_evdev = evdev_alloc(); + evdev_set_name(sc->sc_evdev, device_get_desc(dev)); + evdev_set_phys(sc->sc_evdev, device_get_nameunit(dev)); + evdev_set_id(sc->sc_evdev, hw->idBus, hw->idVendor, hw->idProduct, + hw->idVersion); + evdev_set_serial(sc->sc_evdev, hw->serial); + evdev_support_event(sc->sc_evdev, EV_SYN); + evdev_support_event(sc->sc_evdev, EV_KEY); + evdev_support_event(sc->sc_evdev, EV_REP); + + for (i = 0; i < APPLEIR_NKEYS; i++) { + if (appleir_keymap[i] != KEY_RESERVED) + evdev_support_key(sc->sc_evdev, appleir_keymap[i]); + } + for (i = 0; i < GENERIC_NKEYS; i++) + evdev_support_key(sc->sc_evdev, generic_keymap[i].key); + + error = evdev_register_mtx(sc->sc_evdev, &sc->sc_mtx); + if (error != 0) { + device_printf(dev, "evdev_register_mtx failed: %d\n", error); + goto fail; + } + + hidbus_set_intr(dev, appleir_intr, sc); + + error = hid_intr_start(dev); + if (error != 0) { + device_printf(dev, "hid_intr_start failed: %d\n", error); + goto fail; + } + + return (0); + +fail: + if (sc->sc_evdev != NULL) + evdev_free(sc->sc_evdev); + callout_drain(&sc->sc_co); + callout_drain(&sc->sc_twoco); + mtx_destroy(&sc->sc_mtx); + return (error); +} + +static int +appleir_detach(device_t dev) +{ + struct appleir_softc *sc = device_get_softc(dev); + int error; + + error = hid_intr_stop(dev); + if (error != 0) { + device_printf(dev, "hid_intr_stop failed: %d\n", error); + return (error); + } + callout_drain(&sc->sc_co); + callout_drain(&sc->sc_twoco); + evdev_free(sc->sc_evdev); + mtx_destroy(&sc->sc_mtx); + + return (0); +} + +static device_method_t appleir_methods[] = { + DEVMETHOD(device_probe, appleir_probe), + DEVMETHOD(device_attach, appleir_attach), + DEVMETHOD(device_detach, appleir_detach), + DEVMETHOD_END +}; + +static driver_t appleir_driver = { + "appleir", + appleir_methods, + sizeof(struct appleir_softc) +}; + +DRIVER_MODULE(appleir, hidbus, appleir_driver, NULL, NULL); +MODULE_DEPEND(appleir, hid, 1, 1, 1); +MODULE_DEPEND(appleir, hidbus, 1, 1, 1); +MODULE_DEPEND(appleir, evdev, 1, 1, 1); +MODULE_VERSION(appleir, 1); +HID_PNP_INFO(appleir_devs); diff --git a/sys/dev/hid/bcm5974.c b/sys/dev/hid/bcm5974.c index 442e8905e9bc..e2efeb08eb2e 100644 --- a/sys/dev/hid/bcm5974.c +++ b/sys/dev/hid/bcm5974.c @@ -120,6 +120,7 @@ enum tp_type { /* list of device capability bits */ #define HAS_INTEGRATED_BUTTON 1 #define USES_COMPACT_REPORT 2 +#define SUPPORTS_FORCETOUCH 4 struct tp_type_params { uint8_t caps; /* device capability bitmask */ @@ -146,13 +147,13 @@ struct tp_type_params { .delta = 0, }, [TYPE4] = { - .caps = HAS_INTEGRATED_BUTTON, + .caps = HAS_INTEGRATED_BUTTON | SUPPORTS_FORCETOUCH, .button = 31, .offset = 23 * 2, .delta = 2, }, [TYPE_MT2U] = { - .caps = HAS_INTEGRATED_BUTTON | USES_COMPACT_REPORT, + .caps = HAS_INTEGRATED_BUTTON | USES_COMPACT_REPORT | SUPPORTS_FORCETOUCH, .button = 1, .offset = 12, .delta = 0, @@ -407,6 +408,10 @@ static const struct bcm5974_dev_params bcm5974_dev_params[BCM5974_FLAG_MAX] = { HID_BVPI(BUS_USB, USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i), \ HID_TLC(BCM5974_TLC_PAGE, BCM5974_TLC_USAGE), \ } +#define BCM5974_DEV_USB(v,p,i) { \ + HID_BVPI(BUS_USB, USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i), \ + HID_TLC(HUP_VENDOR_00, 0x0001), \ +} #define APPLE_HID "APP000D" #define BCM5974_DEV_SPI(hid, i) { \ @@ -416,60 +421,60 @@ static const struct bcm5974_dev_params bcm5974_dev_params[BCM5974_FLAG_MAX] = { static const struct hid_device_id bcm5974_devs[] = { /* MacbookAir1.1 */ - BCM5974_DEV(APPLE, WELLSPRING_ANSI, BCM5974_FLAG_WELLSPRING1), - BCM5974_DEV(APPLE, WELLSPRING_ISO, BCM5974_FLAG_WELLSPRING1), - BCM5974_DEV(APPLE, WELLSPRING_JIS, BCM5974_FLAG_WELLSPRING1), + BCM5974_DEV_USB(APPLE, WELLSPRING_ANSI, BCM5974_FLAG_WELLSPRING1), + BCM5974_DEV_USB(APPLE, WELLSPRING_ISO, BCM5974_FLAG_WELLSPRING1), + BCM5974_DEV_USB(APPLE, WELLSPRING_JIS, BCM5974_FLAG_WELLSPRING1), /* MacbookProPenryn, aka wellspring2 */ - BCM5974_DEV(APPLE, WELLSPRING2_ANSI, BCM5974_FLAG_WELLSPRING2), - BCM5974_DEV(APPLE, WELLSPRING2_ISO, BCM5974_FLAG_WELLSPRING2), - BCM5974_DEV(APPLE, WELLSPRING2_JIS, BCM5974_FLAG_WELLSPRING2), + BCM5974_DEV_USB(APPLE, WELLSPRING2_ANSI, BCM5974_FLAG_WELLSPRING2), + BCM5974_DEV_USB(APPLE, WELLSPRING2_ISO, BCM5974_FLAG_WELLSPRING2), + BCM5974_DEV_USB(APPLE, WELLSPRING2_JIS, BCM5974_FLAG_WELLSPRING2), /* Macbook5,1 (unibody), aka wellspring3 */ - BCM5974_DEV(APPLE, WELLSPRING3_ANSI, BCM5974_FLAG_WELLSPRING3), - BCM5974_DEV(APPLE, WELLSPRING3_ISO, BCM5974_FLAG_WELLSPRING3), - BCM5974_DEV(APPLE, WELLSPRING3_JIS, BCM5974_FLAG_WELLSPRING3), + BCM5974_DEV_USB(APPLE, WELLSPRING3_ANSI, BCM5974_FLAG_WELLSPRING3), + BCM5974_DEV_USB(APPLE, WELLSPRING3_ISO, BCM5974_FLAG_WELLSPRING3), + BCM5974_DEV_USB(APPLE, WELLSPRING3_JIS, BCM5974_FLAG_WELLSPRING3), /* MacbookAir3,2 (unibody), aka wellspring4 */ - BCM5974_DEV(APPLE, WELLSPRING4_ANSI, BCM5974_FLAG_WELLSPRING4), - BCM5974_DEV(APPLE, WELLSPRING4_ISO, BCM5974_FLAG_WELLSPRING4), - BCM5974_DEV(APPLE, WELLSPRING4_JIS, BCM5974_FLAG_WELLSPRING4), + BCM5974_DEV_USB(APPLE, WELLSPRING4_ANSI, BCM5974_FLAG_WELLSPRING4), + BCM5974_DEV_USB(APPLE, WELLSPRING4_ISO, BCM5974_FLAG_WELLSPRING4), + BCM5974_DEV_USB(APPLE, WELLSPRING4_JIS, BCM5974_FLAG_WELLSPRING4), /* MacbookAir3,1 (unibody), aka wellspring4 */ - BCM5974_DEV(APPLE, WELLSPRING4A_ANSI, BCM5974_FLAG_WELLSPRING4A), - BCM5974_DEV(APPLE, WELLSPRING4A_ISO, BCM5974_FLAG_WELLSPRING4A), - BCM5974_DEV(APPLE, WELLSPRING4A_JIS, BCM5974_FLAG_WELLSPRING4A), + BCM5974_DEV_USB(APPLE, WELLSPRING4A_ANSI, BCM5974_FLAG_WELLSPRING4A), + BCM5974_DEV_USB(APPLE, WELLSPRING4A_ISO, BCM5974_FLAG_WELLSPRING4A), + BCM5974_DEV_USB(APPLE, WELLSPRING4A_JIS, BCM5974_FLAG_WELLSPRING4A), /* Macbook8 (unibody, March 2011) */ - BCM5974_DEV(APPLE, WELLSPRING5_ANSI, BCM5974_FLAG_WELLSPRING5), - BCM5974_DEV(APPLE, WELLSPRING5_ISO, BCM5974_FLAG_WELLSPRING5), - BCM5974_DEV(APPLE, WELLSPRING5_JIS, BCM5974_FLAG_WELLSPRING5), + BCM5974_DEV_USB(APPLE, WELLSPRING5_ANSI, BCM5974_FLAG_WELLSPRING5), + BCM5974_DEV_USB(APPLE, WELLSPRING5_ISO, BCM5974_FLAG_WELLSPRING5), + BCM5974_DEV_USB(APPLE, WELLSPRING5_JIS, BCM5974_FLAG_WELLSPRING5), /* MacbookAir4,1 (unibody, July 2011) */ - BCM5974_DEV(APPLE, WELLSPRING6A_ANSI, BCM5974_FLAG_WELLSPRING6A), - BCM5974_DEV(APPLE, WELLSPRING6A_ISO, BCM5974_FLAG_WELLSPRING6A), - BCM5974_DEV(APPLE, WELLSPRING6A_JIS, BCM5974_FLAG_WELLSPRING6A), + BCM5974_DEV_USB(APPLE, WELLSPRING6A_ANSI, BCM5974_FLAG_WELLSPRING6A), + BCM5974_DEV_USB(APPLE, WELLSPRING6A_ISO, BCM5974_FLAG_WELLSPRING6A), + BCM5974_DEV_USB(APPLE, WELLSPRING6A_JIS, BCM5974_FLAG_WELLSPRING6A), /* MacbookAir4,2 (unibody, July 2011) */ - BCM5974_DEV(APPLE, WELLSPRING6_ANSI, BCM5974_FLAG_WELLSPRING6), - BCM5974_DEV(APPLE, WELLSPRING6_ISO, BCM5974_FLAG_WELLSPRING6), - BCM5974_DEV(APPLE, WELLSPRING6_JIS, BCM5974_FLAG_WELLSPRING6), + BCM5974_DEV_USB(APPLE, WELLSPRING6_ANSI, BCM5974_FLAG_WELLSPRING6), + BCM5974_DEV_USB(APPLE, WELLSPRING6_ISO, BCM5974_FLAG_WELLSPRING6), + BCM5974_DEV_USB(APPLE, WELLSPRING6_JIS, BCM5974_FLAG_WELLSPRING6), /* Macbook8,2 (unibody) */ - BCM5974_DEV(APPLE, WELLSPRING5A_ANSI, BCM5974_FLAG_WELLSPRING5A), - BCM5974_DEV(APPLE, WELLSPRING5A_ISO, BCM5974_FLAG_WELLSPRING5A), - BCM5974_DEV(APPLE, WELLSPRING5A_JIS, BCM5974_FLAG_WELLSPRING5A), + BCM5974_DEV_USB(APPLE, WELLSPRING5A_ANSI, BCM5974_FLAG_WELLSPRING5A), + BCM5974_DEV_USB(APPLE, WELLSPRING5A_ISO, BCM5974_FLAG_WELLSPRING5A), + BCM5974_DEV_USB(APPLE, WELLSPRING5A_JIS, BCM5974_FLAG_WELLSPRING5A), /* MacbookPro10,1 (unibody, June 2012) */ /* MacbookPro11,1-3 (unibody, June 2013) */ - BCM5974_DEV(APPLE, WELLSPRING7_ANSI, BCM5974_FLAG_WELLSPRING7), - BCM5974_DEV(APPLE, WELLSPRING7_ISO, BCM5974_FLAG_WELLSPRING7), - BCM5974_DEV(APPLE, WELLSPRING7_JIS, BCM5974_FLAG_WELLSPRING7), + BCM5974_DEV_USB(APPLE, WELLSPRING7_ANSI, BCM5974_FLAG_WELLSPRING7), + BCM5974_DEV_USB(APPLE, WELLSPRING7_ISO, BCM5974_FLAG_WELLSPRING7), + BCM5974_DEV_USB(APPLE, WELLSPRING7_JIS, BCM5974_FLAG_WELLSPRING7), - /* MacbookPro10,2 (unibody, October 2012) */ - BCM5974_DEV(APPLE, WELLSPRING7A_ANSI, BCM5974_FLAG_WELLSPRING7A), - BCM5974_DEV(APPLE, WELLSPRING7A_ISO, BCM5974_FLAG_WELLSPRING7A), - BCM5974_DEV(APPLE, WELLSPRING7A_JIS, BCM5974_FLAG_WELLSPRING7A), + /* MacbookPro10,2 (unibody, October 2012) */ + BCM5974_DEV_USB(APPLE, WELLSPRING7A_ANSI, BCM5974_FLAG_WELLSPRING7A), + BCM5974_DEV_USB(APPLE, WELLSPRING7A_ISO, BCM5974_FLAG_WELLSPRING7A), + BCM5974_DEV_USB(APPLE, WELLSPRING7A_JIS, BCM5974_FLAG_WELLSPRING7A), /* MacbookAir6,2 (unibody, June 2013) */ BCM5974_DEV(APPLE, WELLSPRING8_ANSI, BCM5974_FLAG_WELLSPRING8), @@ -748,7 +753,8 @@ bcm5974_attach(device_t dev) BCM5974_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->sc_params->x); BCM5974_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->sc_params->y); /* finger pressure */ - BCM5974_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p); + if ((sc->sc_params->tp->caps & SUPPORTS_FORCETOUCH) != 0) + BCM5974_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p); /* finger touch area */ BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w); BCM5974_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w); diff --git a/sys/dev/hid/hgame.c b/sys/dev/hid/hgame.c index 8dde6b5550c9..693c5afee034 100644 --- a/sys/dev/hid/hgame.c +++ b/sys/dev/hid/hgame.c @@ -134,28 +134,20 @@ hgame_dpad_cb(HIDMAP_CB_ARGS) data = ctx.data; switch (HIDMAP_CB_UDATA64) { case HUG_D_PAD_UP: - if (sc->dpad_down) - return (ENOMSG); - evdev_push_abs(evdev, ABS_HAT0Y, (data == 0) ? 0 : -1); sc->dpad_up = (data != 0); + evdev_push_abs(evdev, ABS_HAT0Y, sc->dpad_down - sc->dpad_up); break; case HUG_D_PAD_DOWN: - if (sc->dpad_up) - return (ENOMSG); - evdev_push_abs(evdev, ABS_HAT0Y, (data == 0) ? 0 : 1); sc->dpad_down = (data != 0); + evdev_push_abs(evdev, ABS_HAT0Y, sc->dpad_down - sc->dpad_up); break; case HUG_D_PAD_RIGHT: - if (sc->dpad_left) - return (ENOMSG); - evdev_push_abs(evdev, ABS_HAT0X, (data == 0) ? 0 : 1); sc->dpad_right = (data != 0); + evdev_push_abs(evdev, ABS_HAT0X, sc->dpad_right - sc->dpad_left); break; case HUG_D_PAD_LEFT: - if (sc->dpad_right) - return (ENOMSG); - evdev_push_abs(evdev, ABS_HAT0X, (data == 0) ? 0 : -1); sc->dpad_left = (data != 0); + evdev_push_abs(evdev, ABS_HAT0X, sc->dpad_right - sc->dpad_left); break; } break; diff --git a/sys/dev/hid/hid.h b/sys/dev/hid/hid.h index e56f8ffe772b..f164e48341ed 100644 --- a/sys/dev/hid/hid.h +++ b/sys/dev/hid/hid.h @@ -57,8 +57,14 @@ #define HUP_SCALE 0x008c #define HUP_CAMERA_CONTROL 0x0090 #define HUP_ARCADE 0x0091 +#define HUP_RESERVED_FF 0x00ff #define HUP_FIDO 0xf1d0 -#define HUP_MICROSOFT 0xff00 +#define HUP_VENDOR_00 0xff00 +#define HUP_VENDOR_01 0xff01 +/* XXX compat */ +#define HUP_APPLE HUP_RESERVED_FF +#define HUP_MICROSOFT HUP_VENDOR_00 +#define HUP_HP HUP_VENDOR_01 /* Usages, generic desktop */ #define HUG_POINTER 0x0001 diff --git a/sys/dev/hid/hidbus.h b/sys/dev/hid/hidbus.h index 3de4a6291511..50b680c41065 100644 --- a/sys/dev/hid/hidbus.h +++ b/sys/dev/hid/hidbus.h @@ -27,7 +27,7 @@ #define _HID_HIDBUS_H_ enum { - HIDBUS_IVAR_USAGE, + HIDBUS_IVAR_USAGE = BUS_IVARS_PRIVATE, HIDBUS_IVAR_INDEX, HIDBUS_IVAR_FLAGS, #define HIDBUS_FLAG_AUTOCHILD (0<<1) /* Child is autodiscovered */ diff --git a/sys/dev/hid/hkbd.c b/sys/dev/hid/hkbd.c index 6255c42d3b62..edfd3f5d4eff 100644 --- a/sys/dev/hid/hkbd.c +++ b/sys/dev/hid/hkbd.c @@ -73,6 +73,8 @@ #include <dev/hid/hidquirk.h> #include <dev/hid/hidrdesc.h> +#include "usbdevs.h" + #ifdef EVDEV_SUPPORT #include <dev/evdev/input.h> #include <dev/evdev/evdev.h> @@ -97,6 +99,9 @@ static int hkbd_debug = 0; #endif static int hkbd_no_leds = 0; +static int hkbd_apple_fn_mode = 0; +static int hkbd_apple_swap_cmd_ctl = 0; +static int hkbd_apple_swap_cmd_opt = 0; static SYSCTL_NODE(_hw_hid, OID_AUTO, hkbd, CTLFLAG_RW, 0, "USB keyboard"); #ifdef HID_DEBUG @@ -105,6 +110,12 @@ SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, debug, CTLFLAG_RWTUN, #endif SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, no_leds, CTLFLAG_RWTUN, &hkbd_no_leds, 0, "Disables setting of keyboard leds"); +SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, apple_fn_mode, CTLFLAG_RWTUN, + &hkbd_apple_fn_mode, 0, "0 = Fn + F1..12 -> media, 1 = F1..F12 -> media"); +SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, apple_swap_cmd_ctl, CTLFLAG_RWTUN, + &hkbd_apple_swap_cmd_ctl, 0, "Swap Command & Control keys"); +SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, apple_swap_cmd_opt, CTLFLAG_RWTUN, + &hkbd_apple_swap_cmd_opt, 0, "Swap Command & Option keys"); #define INPUT_EPOCH global_epoch_preempt @@ -126,6 +137,10 @@ SYSCTL_INT(_hw_hid_hkbd, OID_AUTO, no_leds, CTLFLAG_RWTUN, #define MOD_MIN 0xe0 #define MOD_MAX 0xe7 +/* check evdev_usb_scancodes[] for names */ +#define APPLE_FN_KEY 0xff +#define APPLE_EJECT_KEY 0xec + struct hkbd_softc { device_t sc_dev; @@ -289,9 +304,9 @@ static const uint8_t hkbd_trtab[256] = { NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */ NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */ 29, 42, 56, 105, 90, 54, 93, 106, /* E0 - E7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */ + NN, NN, NN, NN, 254, NN, NN, NN, /* E8 - EF */ NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */ + NN, NN, NN, NN, NN, NN, NN, 255, /* F8 - FF */ }; static const uint8_t hkbd_boot_desc[] = { HID_KBD_BOOTPROTO_DESCR() }; @@ -516,13 +531,14 @@ hkbd_interrupt(struct hkbd_softc *sc) continue; hkbd_put_key(sc, key | KEY_PRESS); - sc->sc_co_basetime = sbinuptime(); - sc->sc_delay = sc->sc_kbd.kb_delay1; - hkbd_start_timer(sc); - - /* set repeat time for last key */ - sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1; - sc->sc_repeat_key = key; + if (key != APPLE_FN_KEY) { + sc->sc_co_basetime = sbinuptime(); + sc->sc_delay = sc->sc_kbd.kb_delay1; + hkbd_start_timer(sc); + /* set repeat time for last key */ + sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1; + sc->sc_repeat_key = key; + } } /* synchronize old data with new data */ @@ -613,6 +629,16 @@ static uint32_t hkbd_apple_fn(uint32_t keycode) { switch (keycode) { + case 0x0b: return 0x50; /* H -> LEFT ARROW */ + case 0x0d: return 0x51; /* J -> DOWN ARROW */ + case 0x0e: return 0x52; /* K -> UP ARROW */ + case 0x0f: return 0x4f; /* L -> RIGHT ARROW */ + case 0x36: return 0x4a; /* COMMA -> HOME */ + case 0x37: return 0x4d; /* DOT -> END */ + case 0x18: return 0x4b; /* U -> PGUP */ + case 0x07: return 0x4e; /* D -> PGDN */ + case 0x16: return 0x47; /* S -> SCROLLLOCK */ + case 0x13: return 0x46; /* P -> SYSRQ/PRTSC */ case 0x28: return 0x49; /* RETURN -> INSERT */ case 0x2a: return 0x4c; /* BACKSPACE -> DEL */ case 0x50: return 0x4a; /* LEFT ARROW -> HOME */ @@ -623,6 +649,51 @@ hkbd_apple_fn(uint32_t keycode) } } +/* separate so the sysctl doesn't butcher non-fn keys */ +static uint32_t +hkbd_apple_fn_media(uint32_t keycode) +{ + switch (keycode) { + case 0x3a: return 0xc0; /* F1 -> BRIGHTNESS DOWN */ + case 0x3b: return 0xc1; /* F2 -> BRIGHTNESS UP */ + case 0x3c: return 0xc2; /* F3 -> SCALE (MISSION CTRL)*/ + case 0x3d: return 0xc3; /* F4 -> DASHBOARD (LAUNCHPAD) */ + case 0x3e: return 0xc4; /* F5 -> KBD BACKLIGHT DOWN */ + case 0x3f: return 0xc5; /* F6 -> KBD BACKLIGHT UP */ + case 0x40: return 0xea; /* F7 -> MEDIA PREV */ + case 0x41: return 0xe8; /* F8 -> PLAY/PAUSE */ + case 0x42: return 0xeb; /* F9 -> MEDIA NEXT */ + case 0x43: return 0xef; /* F10 -> MUTE */ + case 0x44: return 0xee; /* F11 -> VOLUME DOWN */ + case 0x45: return 0xed; /* F12 -> VOLUME UP */ + default: return keycode; + } +} + +static uint32_t +hkbd_apple_doswap_cmd_ctl(uint32_t keycode) +{ + switch (keycode) { + case 0xe3: return 0xe0; /* LCMD -> LCTL */ + case 0xe7: return 0xe4; /* RCMD -> RCTL */ + case 0xe0: return 0xe3; /* LCTL -> LCMD */ + case 0xe4: return 0xe7; /* RCTL -> RCMD */ + default: return keycode; + } +} + +static uint32_t +hkbd_apple_doswap_cmd_opt(uint32_t keycode) +{ + switch (keycode) { + case 0xe3: return 0xe2; /* LCMD -> ROPT */ + case 0xe7: return 0xe6; /* RCMD -> ROPT */ + case 0xe2: return 0xe3; /* LOPT -> LCMD */ + case 0xe6: return 0xe7; /* ROPT -> RCMD */ + default: return keycode; + } +} + static uint32_t hkbd_apple_swap(uint32_t keycode) { @@ -675,18 +746,30 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len) /* clear modifiers */ modifiers = 0; - /* scan through HID data */ + /* scan through HID data and expose magic apple keys */ if ((sc->sc_flags & HKBD_FLAG_APPLE_EJECT) && (id == sc->sc_id_apple_eject)) { - if (hid_get_data(buf, len, &sc->sc_loc_apple_eject)) + if (hid_get_data(buf, len, &sc->sc_loc_apple_eject)) { + bit_set(sc->sc_ndata, APPLE_EJECT_KEY); modifiers |= MOD_EJECT; + } else { + bit_clear(sc->sc_ndata, APPLE_EJECT_KEY); + } } if ((sc->sc_flags & HKBD_FLAG_APPLE_FN) && (id == sc->sc_id_apple_fn)) { - if (hid_get_data(buf, len, &sc->sc_loc_apple_fn)) + if (hid_get_data(buf, len, &sc->sc_loc_apple_fn)) { + bit_set(sc->sc_ndata, APPLE_FN_KEY); modifiers |= MOD_FN; + } else { + bit_clear(sc->sc_ndata, APPLE_FN_KEY); + } } + int apply_apple_fn_media = (modifiers & MOD_FN) ? 1 : 0; + if (hkbd_apple_fn_mode) /* toggle from sysctl value */ + apply_apple_fn_media = !apply_apple_fn_media; + bit_foreach(sc->sc_loc_key_valid, HKBD_NKEYCODE, i) { if (id != sc->sc_id_loc_key[i]) { continue; /* invalid HID ID */ @@ -710,6 +793,12 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len) } if (modifiers & MOD_FN) key = hkbd_apple_fn(key); + if (apply_apple_fn_media) + key = hkbd_apple_fn_media(key); + if (hkbd_apple_swap_cmd_ctl) + key = hkbd_apple_doswap_cmd_ctl(key); + if (hkbd_apple_swap_cmd_opt) + key = hkbd_apple_doswap_cmd_opt(key); if (sc->sc_flags & HKBD_FLAG_APPLE_SWAP) key = hkbd_apple_swap(key); if (key == KEY_NONE || key >= HKBD_NKEYCODE) @@ -723,6 +812,12 @@ hkbd_intr_callback(void *context, void *data, hid_size_t len) if (modifiers & MOD_FN) key = hkbd_apple_fn(key); + if (apply_apple_fn_media) + key = hkbd_apple_fn_media(key); + if (hkbd_apple_swap_cmd_ctl) + key = hkbd_apple_doswap_cmd_ctl(key); + if (hkbd_apple_swap_cmd_opt) + key = hkbd_apple_doswap_cmd_opt(key); if (sc->sc_flags & HKBD_FLAG_APPLE_SWAP) key = hkbd_apple_swap(key); if (key == KEY_NONE || key == KEY_ERROR || key >= HKBD_NKEYCODE) @@ -783,25 +878,43 @@ hkbd_parse_hid(struct hkbd_softc *sc, const uint8_t *ptr, uint32_t len, sc->sc_kbd_size = hid_report_size_max(ptr, len, hid_input, &sc->sc_kbd_id); + const struct hid_device_info *hw = hid_get_device_info(sc->sc_dev); + /* investigate if this is an Apple Keyboard */ - if (hidbus_locate(ptr, len, - HID_USAGE2(HUP_CONSUMER, HUG_APPLE_EJECT), - hid_input, tlc_index, 0, &sc->sc_loc_apple_eject, &flags, - &sc->sc_id_apple_eject, NULL)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= HKBD_FLAG_APPLE_EJECT | - HKBD_FLAG_APPLE_SWAP; - DPRINTFN(1, "Found Apple eject-key\n"); - } - if (hidbus_locate(ptr, len, - HID_USAGE2(0xFFFF, 0x0003), - hid_input, tlc_index, 0, &sc->sc_loc_apple_fn, &flags, - &sc->sc_id_apple_fn, NULL)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= HKBD_FLAG_APPLE_FN; - DPRINTFN(1, "Found Apple FN-key\n"); + if (hw->idVendor == USB_VENDOR_APPLE) { /* belt & braces! */ + if (hidbus_locate(ptr, len, + HID_USAGE2(HUP_CONSUMER, HUG_APPLE_EJECT), + hid_input, tlc_index, 0, &sc->sc_loc_apple_eject, &flags, + &sc->sc_id_apple_eject, NULL)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= HKBD_FLAG_APPLE_EJECT | + HKBD_FLAG_APPLE_SWAP; + DPRINTFN(1, "Found Apple eject-key\n"); + } + /* + * check the same vendor pages that linux does to find the one + * apple uses for the function key. + */ + static const uint16_t apple_pages[] = { + HUP_APPLE, /* HID_UP_CUSTOM in linux */ + HUP_MICROSOFT, /* HID_UP_MSVENDOR in linux */ + HUP_HP, /* HID_UP_HPVENDOR2 in linux */ + 0xFFFF /* Original FreeBSD check (Remove?) */ + }; + for (int i = 0; i < (int)nitems(apple_pages); i++) { + if (hidbus_locate(ptr, len, + HID_USAGE2(apple_pages[i], 0x0003), + hid_input, tlc_index, 0, &sc->sc_loc_apple_fn, &flags, + &sc->sc_id_apple_fn, NULL)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= HKBD_FLAG_APPLE_FN; + DPRINTFN(1, "Found Apple FN-key on page 0x%04x\n", + apple_pages[i]); + break; + } + } } - + /* figure out event buffer */ if (hidbus_locate(ptr, len, HID_USAGE2(HUP_KEYBOARD, 0x00), diff --git a/sys/dev/hid/hpen.c b/sys/dev/hid/hpen.c index c298dea57042..fb1f0c96bcba 100644 --- a/sys/dev/hid/hpen.c +++ b/sys/dev/hid/hpen.c @@ -56,7 +56,7 @@ static const uint8_t hpen_graphire_report_descr[] = static const uint8_t hpen_graphire3_4x5_report_descr[] = { HID_GRAPHIRE3_4X5_REPORT_DESCR() }; -static hidmap_cb_t hpen_battery_strenght_cb; +static hidmap_cb_t hpen_battery_strength_cb; static hidmap_cb_t hpen_final_pen_cb; #define HPEN_MAP_BUT(usage, code) \ @@ -77,7 +77,7 @@ static const struct hidmap_item hpen_map_pen[] = { { HPEN_MAP_ABS( Y_TILT, ABS_TILT_Y) }, { HPEN_MAP_ABS( CONTACTID, 0), .forbidden = true }, { HPEN_MAP_ABS( CONTACTCOUNT, 0), .forbidden = true }, - { HPEN_MAP_ABS_CB(BATTERY_STRENGTH, hpen_battery_strenght_cb) }, + { HPEN_MAP_ABS_CB(BATTERY_STRENGTH, hpen_battery_strength_cb) }, { HPEN_MAP_BUT( TOUCH, BTN_TOUCH) }, { HPEN_MAP_BUT( TIP_SWITCH, BTN_TOUCH) }, { HPEN_MAP_BUT( SEC_TIP_SWITCH, BTN_TOUCH) }, @@ -109,7 +109,7 @@ static const struct hid_device_id hpen_devs_no_load[] = { }; static int -hpen_battery_strenght_cb(HIDMAP_CB_ARGS) +hpen_battery_strength_cb(HIDMAP_CB_ARGS) { struct evdev_dev *evdev = HIDMAP_CB_GET_EVDEV(); diff --git a/sys/dev/hpt27xx/hpt27xx_osm_bsd.c b/sys/dev/hpt27xx/hpt27xx_osm_bsd.c index e086a1554940..38bc91f733aa 100644 --- a/sys/dev/hpt27xx/hpt27xx_osm_bsd.c +++ b/sys/dev/hpt27xx/hpt27xx_osm_bsd.c @@ -1258,7 +1258,7 @@ static device_method_t driver_methods[] = { DEVMETHOD(device_attach, hpt_attach), DEVMETHOD(device_detach, hpt_detach), DEVMETHOD(device_shutdown, hpt_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t hpt_pci_driver = { @@ -1271,13 +1271,9 @@ static driver_t hpt_pci_driver = { #error "no TARGETNAME found" #endif -/* use this to make TARGETNAME be expanded */ -#define __DRIVER_MODULE(p1, p2, p3, p4, p5) DRIVER_MODULE(p1, p2, p3, p4, p5) -#define __MODULE_VERSION(p1, p2) MODULE_VERSION(p1, p2) -#define __MODULE_DEPEND(p1, p2, p3, p4, p5) MODULE_DEPEND(p1, p2, p3, p4, p5) -__DRIVER_MODULE(TARGETNAME, pci, hpt_pci_driver, 0, 0); -__MODULE_VERSION(TARGETNAME, 1); -__MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1); +DRIVER_MODULE(TARGETNAME, pci, hpt_pci_driver, NULL, NULL); +MODULE_VERSION(TARGETNAME, 1); +MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1); static int hpt_open(struct cdev *dev, int flags, int devtype, struct thread *td) { diff --git a/sys/dev/hptiop/hptiop.c b/sys/dev/hptiop/hptiop.c index b7b885a7c732..e31b75187e73 100644 --- a/sys/dev/hptiop/hptiop.c +++ b/sys/dev/hptiop/hptiop.c @@ -1728,7 +1728,7 @@ static device_method_t driver_methods[] = { DEVMETHOD(device_attach, hptiop_attach), DEVMETHOD(device_detach, hptiop_detach), DEVMETHOD(device_shutdown, hptiop_shutdown), - { 0, 0 } + DEVMETHOD_END }; static struct hptiop_adapter_ops hptiop_itl_ops = { diff --git a/sys/dev/hptmv/entry.c b/sys/dev/hptmv/entry.c index f3d58f285b39..a82ffb66bdc8 100644 --- a/sys/dev/hptmv/entry.c +++ b/sys/dev/hptmv/entry.c @@ -95,8 +95,7 @@ static driver_t hpt_pci_driver = { sizeof(IAL_ADAPTER_T) }; -#define __DRIVER_MODULE(p1, p2, p3, p4, p5) DRIVER_MODULE(p1, p2, p3, p4, p5) -__DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, 0, 0); +DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, NULL, NULL); MODULE_DEPEND(PROC_DIR_NAME, cam, 1, 1, 1); #define ccb_ccb_ptr spriv_ptr0 diff --git a/sys/dev/hptnr/hptnr_osm_bsd.c b/sys/dev/hptnr/hptnr_osm_bsd.c index 7426873964fb..f3af3b767a77 100644 --- a/sys/dev/hptnr/hptnr_osm_bsd.c +++ b/sys/dev/hptnr/hptnr_osm_bsd.c @@ -1548,7 +1548,7 @@ static device_method_t driver_methods[] = { DEVMETHOD(device_attach, hpt_attach), DEVMETHOD(device_detach, hpt_detach), DEVMETHOD(device_shutdown, hpt_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t hpt_pci_driver = { @@ -1561,13 +1561,9 @@ static driver_t hpt_pci_driver = { #error "no TARGETNAME found" #endif -/* use this to make TARGETNAME be expanded */ -#define __DRIVER_MODULE(p1, p2, p3, p4, p5) DRIVER_MODULE(p1, p2, p3, p4, p5) -#define __MODULE_VERSION(p1, p2) MODULE_VERSION(p1, p2) -#define __MODULE_DEPEND(p1, p2, p3, p4, p5) MODULE_DEPEND(p1, p2, p3, p4, p5) -__DRIVER_MODULE(TARGETNAME, pci, hpt_pci_driver, 0, 0); -__MODULE_VERSION(TARGETNAME, 1); -__MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1); +DRIVER_MODULE(TARGETNAME, pci, hpt_pci_driver, NULL, NULL); +MODULE_VERSION(TARGETNAME, 1); +MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1); static int hpt_open(struct cdev *dev, int flags, int devtype, struct thread *td) { diff --git a/sys/dev/hptrr/hptrr_osm_bsd.c b/sys/dev/hptrr/hptrr_osm_bsd.c index 78a051d54cf8..f4ae6732ea5d 100644 --- a/sys/dev/hptrr/hptrr_osm_bsd.c +++ b/sys/dev/hptrr/hptrr_osm_bsd.c @@ -1204,13 +1204,9 @@ static driver_t hpt_pci_driver = { #error "no TARGETNAME found" #endif -/* use this to make TARGETNAME be expanded */ -#define __DRIVER_MODULE(p1, p2, p3, p4, p5) DRIVER_MODULE(p1, p2, p3, p4, p5) -#define __MODULE_VERSION(p1, p2) MODULE_VERSION(p1, p2) -#define __MODULE_DEPEND(p1, p2, p3, p4, p5) MODULE_DEPEND(p1, p2, p3, p4, p5) -__DRIVER_MODULE(TARGETNAME, pci, hpt_pci_driver, 0, 0); -__MODULE_VERSION(TARGETNAME, 1); -__MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1); +DRIVER_MODULE(TARGETNAME, pci, hpt_pci_driver, NULL, NULL); +MODULE_VERSION(TARGETNAME, 1); +MODULE_DEPEND(TARGETNAME, cam, 1, 1, 1); static int hpt_open(struct cdev *dev, int flags, int devtype, struct thread *td) { diff --git a/sys/dev/hwpmc/hwpmc_amd.c b/sys/dev/hwpmc/hwpmc_amd.c index d2fb17549990..51505bfcff37 100644 --- a/sys/dev/hwpmc/hwpmc_amd.c +++ b/sys/dev/hwpmc/hwpmc_amd.c @@ -53,44 +53,15 @@ DPCPU_DEFINE_STATIC(uint32_t, nmi_counter); /* AMD K8 PMCs */ struct amd_descr { - struct pmc_descr pm_descr; /* "base class" */ - uint32_t pm_evsel; /* address of EVSEL register */ - uint32_t pm_perfctr; /* address of PERFCTR register */ -}; - -/* Counter hardware. */ -#define PMCDESC(evsel, perfctr) \ - { \ - .pm_descr = { \ - .pd_name = "", \ - .pd_class = PMC_CLASS_K8, \ - .pd_caps = AMD_PMC_CAPS, \ - .pd_width = 48 \ - }, \ - .pm_evsel = (evsel), \ - .pm_perfctr = (perfctr) \ - } - -static struct amd_descr amd_pmcdesc[AMD_NPMCS] = -{ - PMCDESC(AMD_PMC_EVSEL_0, AMD_PMC_PERFCTR_0), - PMCDESC(AMD_PMC_EVSEL_1, AMD_PMC_PERFCTR_1), - PMCDESC(AMD_PMC_EVSEL_2, AMD_PMC_PERFCTR_2), - PMCDESC(AMD_PMC_EVSEL_3, AMD_PMC_PERFCTR_3), - PMCDESC(AMD_PMC_EVSEL_4, AMD_PMC_PERFCTR_4), - PMCDESC(AMD_PMC_EVSEL_5, AMD_PMC_PERFCTR_5), - PMCDESC(AMD_PMC_EVSEL_EP_L3_0, AMD_PMC_PERFCTR_EP_L3_0), - PMCDESC(AMD_PMC_EVSEL_EP_L3_1, AMD_PMC_PERFCTR_EP_L3_1), - PMCDESC(AMD_PMC_EVSEL_EP_L3_2, AMD_PMC_PERFCTR_EP_L3_2), - PMCDESC(AMD_PMC_EVSEL_EP_L3_3, AMD_PMC_PERFCTR_EP_L3_3), - PMCDESC(AMD_PMC_EVSEL_EP_L3_4, AMD_PMC_PERFCTR_EP_L3_4), - PMCDESC(AMD_PMC_EVSEL_EP_L3_5, AMD_PMC_PERFCTR_EP_L3_5), - PMCDESC(AMD_PMC_EVSEL_EP_DF_0, AMD_PMC_PERFCTR_EP_DF_0), - PMCDESC(AMD_PMC_EVSEL_EP_DF_1, AMD_PMC_PERFCTR_EP_DF_1), - PMCDESC(AMD_PMC_EVSEL_EP_DF_2, AMD_PMC_PERFCTR_EP_DF_2), - PMCDESC(AMD_PMC_EVSEL_EP_DF_3, AMD_PMC_PERFCTR_EP_DF_3) + struct pmc_descr pm_descr; /* "base class" */ + uint32_t pm_evsel; /* address of EVSEL register */ + uint32_t pm_perfctr; /* address of PERFCTR register */ + enum sub_class pm_subclass; /* register subclass */ }; +static int amd_npmcs; +static int amd_core_npmcs, amd_l3_npmcs, amd_df_npmcs; +static struct amd_descr amd_pmcdesc[AMD_NPMCS_MAX]; struct amd_event_code_map { enum pmc_event pe_ev; /* enum value */ uint16_t pe_code; /* encoded event mask */ @@ -203,7 +174,7 @@ const int amd_event_codes_size = nitems(amd_event_codes); * Per-processor information */ struct amd_cpu { - struct pmc_hw pc_amdpmcs[AMD_NPMCS]; + struct pmc_hw pc_amdpmcs[AMD_NPMCS_MAX]; }; static struct amd_cpu **amd_pcpu; @@ -219,7 +190,7 @@ amd_read_pmc(int cpu, int ri, struct pmc *pm, pmc_value_t *v) KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[amd,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < AMD_NPMCS, + KASSERT(ri >= 0 && ri < amd_npmcs, ("[amd,%d] illegal row-index %d", __LINE__, ri)); KASSERT(amd_pcpu[cpu], ("[amd,%d] null per-cpu, cpu %d", __LINE__, cpu)); @@ -264,7 +235,7 @@ amd_write_pmc(int cpu, int ri, struct pmc *pm, pmc_value_t v) KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[amd,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < AMD_NPMCS, + KASSERT(ri >= 0 && ri < amd_npmcs, ("[amd,%d] illegal row-index %d", __LINE__, ri)); pd = &amd_pmcdesc[ri]; @@ -293,7 +264,7 @@ amd_config_pmc(int cpu, int ri, struct pmc *pm) KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[amd,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < AMD_NPMCS, + KASSERT(ri >= 0 && ri < amd_npmcs, ("[amd,%d] illegal row-index %d", __LINE__, ri)); phw = &amd_pcpu[cpu]->pc_amdpmcs[ri]; @@ -362,7 +333,7 @@ amd_allocate_pmc(int cpu __unused, int ri, struct pmc *pm, enum pmc_event pe; int i; - KASSERT(ri >= 0 && ri < AMD_NPMCS, + KASSERT(ri >= 0 && ri < amd_npmcs, ("[amd,%d] illegal row index %d", __LINE__, ri)); pd = &amd_pmcdesc[ri].pm_descr; @@ -376,17 +347,14 @@ amd_allocate_pmc(int cpu __unused, int ri, struct pmc *pm, caps = pm->pm_caps; + if (((caps & PMC_CAP_PRECISE) != 0) && + ((pd->pd_caps & PMC_CAP_PRECISE) == 0)) + return (EINVAL); + PMCDBG2(MDP, ALL, 1,"amd-allocate ri=%d caps=0x%x", ri, caps); /* Validate sub-class. */ - if ((ri >= 0 && ri < 6) && a->pm_md.pm_amd.pm_amd_sub_class != - PMC_AMD_SUB_CLASS_CORE) - return (EINVAL); - if ((ri >= 6 && ri < 12) && a->pm_md.pm_amd.pm_amd_sub_class != - PMC_AMD_SUB_CLASS_L3_CACHE) - return (EINVAL); - if ((ri >= 12 && ri < 16) && a->pm_md.pm_amd.pm_amd_sub_class != - PMC_AMD_SUB_CLASS_DATA_FABRIC) + if (amd_pmcdesc[ri].pm_subclass != a->pm_md.pm_amd.pm_amd_sub_class) return (EINVAL); if (strlen(pmc_cpuid) != 0) { @@ -396,6 +364,9 @@ amd_allocate_pmc(int cpu __unused, int ri, struct pmc *pm, return (0); } + /* + * Everything below this is for supporting older processors. + */ pe = a->pm_ev; /* map ev to the correct event mask code */ @@ -455,7 +426,7 @@ amd_release_pmc(int cpu, int ri, struct pmc *pmc __unused) KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[amd,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < AMD_NPMCS, + KASSERT(ri >= 0 && ri < amd_npmcs, ("[amd,%d] illegal row-index %d", __LINE__, ri)); phw = &amd_pcpu[cpu]->pc_amdpmcs[ri]; @@ -477,13 +448,18 @@ amd_start_pmc(int cpu __diagused, int ri, struct pmc *pm) KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[amd,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < AMD_NPMCS, + KASSERT(ri >= 0 && ri < amd_npmcs, ("[amd,%d] illegal row-index %d", __LINE__, ri)); pd = &amd_pmcdesc[ri]; PMCDBG2(MDP, STA, 1, "amd-start cpu=%d ri=%d", cpu, ri); + /* + * Triggered by DF counters because all DF MSRs are shared. We need to + * change the code to honor the per-package flag in the JSON event + * definitions. + */ KASSERT(AMD_PMC_IS_STOPPED(pd->pm_evsel), ("[amd,%d] pmc%d,cpu%d: Starting active PMC \"%s\"", __LINE__, ri, cpu, pd->pm_descr.pd_name)); @@ -509,7 +485,7 @@ amd_stop_pmc(int cpu __diagused, int ri, struct pmc *pm) KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[amd,%d] illegal CPU value %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < AMD_NPMCS, + KASSERT(ri >= 0 && ri < amd_npmcs, ("[amd,%d] illegal row-index %d", __LINE__, ri)); pd = &amd_pmcdesc[ri]; @@ -567,6 +543,10 @@ amd_intr(struct trapframe *tf) pac = amd_pcpu[cpu]; + retval = pmc_ibs_intr(tf); + if (retval) + goto done; + /* * look for all PMCs that have interrupted: * - look for a running, sampling PMC which has overflowed @@ -578,7 +558,10 @@ amd_intr(struct trapframe *tf) * a single interrupt. Check all the valid pmcs for * overflow. */ - for (i = 0; i < AMD_CORE_NPMCS; i++) { + for (i = 0; i < amd_npmcs; i++) { + if (amd_pmcdesc[i].pm_subclass != PMC_AMD_SUB_CLASS_CORE) + break; + if ((pm = pac->pc_amdpmcs[i].phw_pmc) == NULL || !PMC_IS_SAMPLING_MODE(PMC_TO_MODE(pm))) { continue; @@ -634,6 +617,7 @@ amd_intr(struct trapframe *tf) } } +done: if (retval) counter_u64_add(pmc_stats.pm_intr_processed, 1); else @@ -654,7 +638,7 @@ amd_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), ("[amd,%d] illegal CPU %d", __LINE__, cpu)); - KASSERT(ri >= 0 && ri < AMD_NPMCS, + KASSERT(ri >= 0 && ri < amd_npmcs, ("[amd,%d] row-index %d out of range", __LINE__, ri)); phw = &amd_pcpu[cpu]->pc_amdpmcs[ri]; @@ -680,10 +664,55 @@ amd_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) static int amd_get_msr(int ri, uint32_t *msr) { - KASSERT(ri >= 0 && ri < AMD_NPMCS, + int df_idx; + + KASSERT(ri >= 0 && ri < amd_npmcs, ("[amd,%d] ri %d out of range", __LINE__, ri)); - *msr = amd_pmcdesc[ri].pm_perfctr - AMD_PMC_PERFCTR_0; + /* + * Map counter row index to RDPMC ECX value. + * + * AMD BKDG 24594 rev 3.37, page 440, + * "RDPMC Read Performance-Monitoring Counter": + * ECX 0-5: Core counters 0-5 + * ECX 6-9: DF/Northbridge counters 0-3 + * ECX 10-15: L3 Cache counters 0-5 + * ECX 16-27: DF/Northbridge counters 4-15 + * + * AMD PPR 57930-A0 section 2.1.9, + * "Register Sharing" for DF counter details. + */ + if (ri < amd_core_npmcs) { + /* ECX 0-5: Core counters */ + *msr = ri; + } else if (ri < amd_core_npmcs + amd_l3_npmcs) { + /* ECX 10-15: L3 Cache counters */ + *msr = 10 + (ri - amd_core_npmcs); + } else { + /* ECX 6-9: DF counters 0-3 + * ECX 16-27: DF counters 4-15 */ + df_idx = ri - amd_core_npmcs - amd_l3_npmcs; + if (df_idx < 4) + *msr = 6 + df_idx; + else if (df_idx < 16) + *msr = 16 + (df_idx - 4); + else + return (EINVAL); + } + return (0); +} + +/* + * Return the capabilities of the given PMC. + */ +static int +amd_get_caps(int ri, uint32_t *caps) +{ + KASSERT(ri >= 0 && ri < amd_npmcs, + ("[amd,%d] ri %d out of range", __LINE__, ri)); + + *caps = amd_pmcdesc[ri].pm_descr.pd_caps; + return (0); } @@ -715,7 +744,7 @@ amd_pcpu_init(struct pmc_mdep *md, int cpu) KASSERT(pc != NULL, ("[amd,%d] NULL per-cpu pointer", __LINE__)); - for (n = 0, phw = pac->pc_amdpmcs; n < AMD_NPMCS; n++, phw++) { + for (n = 0, phw = pac->pc_amdpmcs; n < amd_npmcs; n++, phw++) { phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(n); phw->phw_pmc = NULL; @@ -733,7 +762,6 @@ amd_pcpu_fini(struct pmc_mdep *md, int cpu) { struct amd_cpu *pac; struct pmc_cpu *pc; - uint32_t evsel; int first_ri, i; KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), @@ -742,15 +770,6 @@ amd_pcpu_fini(struct pmc_mdep *md, int cpu) PMCDBG1(MDP, INI, 1, "amd-cleanup cpu=%d", cpu); /* - * First, turn off all PMCs on this CPU. - */ - for (i = 0; i < 4; i++) { /* XXX this loop is now not needed */ - evsel = rdmsr(AMD_PMC_EVSEL_0 + i); - evsel &= ~AMD_PMC_ENABLE; - wrmsr(AMD_PMC_EVSEL_0 + i, evsel); - } - - /* * Next, free up allocated space. */ if ((pac = amd_pcpu[cpu]) == NULL) @@ -759,7 +778,7 @@ amd_pcpu_fini(struct pmc_mdep *md, int cpu) amd_pcpu[cpu] = NULL; #ifdef HWPMC_DEBUG - for (i = 0; i < AMD_NPMCS; i++) { + for (i = 0; i < AMD_NPMCS_K8; i++) { KASSERT(pac->pc_amdpmcs[i].phw_pmc == NULL, ("[amd,%d] CPU%d/PMC%d in use", __LINE__, cpu, i)); KASSERT(AMD_PMC_IS_STOPPED(AMD_PMC_EVSEL_0 + i), @@ -775,7 +794,7 @@ amd_pcpu_fini(struct pmc_mdep *md, int cpu) /* * Reset pointers in the MI 'per-cpu' state. */ - for (i = 0; i < AMD_NPMCS; i++) + for (i = 0; i < amd_npmcs; i++) pc->pc_hwpmcs[i + first_ri] = NULL; free(pac, M_PMC); @@ -791,8 +810,9 @@ pmc_amd_initialize(void) struct pmc_classdep *pcd; struct pmc_mdep *pmc_mdep; enum pmc_cputype cputype; - int error, i, ncpus; + int error, i, ncpus, nclasses; int family, model, stepping; + struct amd_descr *d; /* * The presence of hardware performance counters on the AMD @@ -824,6 +844,88 @@ pmc_amd_initialize(void) } /* + * From PPR for AMD Family 1Ah, a new cpuid leaf specifies the maximum + * number of PMCs of each type. If we do not have that leaf, we use + * the prior default values that are only valid if we have the feature + * bit enabled in CPU. + */ + if ((amd_feature2 & AMDID2_PCXC) != 0) { + amd_core_npmcs = AMD_PMC_CORE_DEFAULT; + } else { + amd_core_npmcs = AMD_NPMCS_K8; + } + amd_l3_npmcs = AMD_PMC_L3_DEFAULT; + amd_df_npmcs = AMD_PMC_DF_DEFAULT; + + if (cpu_exthigh >= CPUID_EXTPERFMON) { + u_int regs[4]; + do_cpuid(CPUID_EXTPERFMON, regs); + if (regs[1] != 0) { + amd_core_npmcs = EXTPERFMON_CORE_PMCS(regs[1]); + amd_df_npmcs = EXTPERFMON_DF_PMCS(regs[1]); + } + } + + /* Enable the newer core counters */ + for (i = 0; i < amd_core_npmcs; i++) { + d = &amd_pmcdesc[i]; + snprintf(d->pm_descr.pd_name, PMC_NAME_MAX, + "K8-%d", i); + d->pm_descr.pd_class = PMC_CLASS_K8; + d->pm_descr.pd_caps = AMD_PMC_CAPS; + /* + * Zen 5 can precisely count retire events. + * + * Refer to PPR Vol 1 for AMD Family 1Ah Model 02h C1 57238 + * Rev. 0.24 September 29, 2024. + */ + if ((family >= 0x1a) && (i == 2)) + d->pm_descr.pd_caps |= PMC_CAP_PRECISE; + d->pm_descr.pd_width = 48; + if ((amd_feature2 & AMDID2_PCXC) != 0) { + d->pm_evsel = AMD_PMC_CORE_BASE + 2 * i; + d->pm_perfctr = AMD_PMC_CORE_BASE + 2 * i + 1; + } else { + d->pm_evsel = AMD_PMC_EVSEL_0 + i; + d->pm_perfctr = AMD_PMC_PERFCTR_0 + i; + } + d->pm_subclass = PMC_AMD_SUB_CLASS_CORE; + } + amd_npmcs = amd_core_npmcs; + + if ((amd_feature2 & AMDID2_PTSCEL2I) != 0) { + /* Enable the LLC/L3 counters */ + for (i = 0; i < amd_l3_npmcs; i++) { + d = &amd_pmcdesc[amd_npmcs + i]; + snprintf(d->pm_descr.pd_name, PMC_NAME_MAX, + "K8-L3-%d", i); + d->pm_descr.pd_class = PMC_CLASS_K8; + d->pm_descr.pd_caps = AMD_PMC_L3_CAPS; + d->pm_descr.pd_width = 48; + d->pm_evsel = AMD_PMC_L3_BASE + 2 * i; + d->pm_perfctr = AMD_PMC_L3_BASE + 2 * i + 1; + d->pm_subclass = PMC_AMD_SUB_CLASS_L3_CACHE; + } + amd_npmcs += amd_l3_npmcs; + } + + if ((amd_feature2 & AMDID2_PNXC) != 0) { + /* Enable the data fabric counters */ + for (i = 0; i < amd_df_npmcs; i++) { + d = &amd_pmcdesc[amd_npmcs + i]; + snprintf(d->pm_descr.pd_name, PMC_NAME_MAX, + "K8-DF-%d", i); + d->pm_descr.pd_class = PMC_CLASS_K8; + d->pm_descr.pd_caps = AMD_PMC_DF_CAPS; + d->pm_descr.pd_width = 48; + d->pm_evsel = AMD_PMC_DF_BASE + 2 * i; + d->pm_perfctr = AMD_PMC_DF_BASE + 2 * i + 1; + d->pm_subclass = PMC_AMD_SUB_CLASS_DATA_FABRIC; + } + amd_npmcs += amd_df_npmcs; + } + + /* * Allocate space for pointers to PMC HW descriptors and for * the MDEP structure used by MI code. */ @@ -831,10 +933,16 @@ pmc_amd_initialize(void) M_WAITOK | M_ZERO); /* - * These processors have two classes of PMCs: the TSC and - * programmable PMCs. + * These processors have two or three classes of PMCs: the TSC, + * programmable PMCs, and AMD IBS. */ - pmc_mdep = pmc_mdep_alloc(2); + if ((amd_feature2 & AMDID2_IBS) != 0) { + nclasses = 3; + } else { + nclasses = 2; + } + + pmc_mdep = pmc_mdep_alloc(nclasses); ncpus = pmc_cpu_max(); @@ -848,16 +956,10 @@ pmc_amd_initialize(void) pcd->pcd_caps = AMD_PMC_CAPS; pcd->pcd_class = PMC_CLASS_K8; - pcd->pcd_num = AMD_NPMCS; + pcd->pcd_num = amd_npmcs; pcd->pcd_ri = pmc_mdep->pmd_npmc; pcd->pcd_width = 48; - /* fill in the correct pmc name and class */ - for (i = 0; i < AMD_NPMCS; i++) { - snprintf(amd_pmcdesc[i].pm_descr.pd_name, PMC_NAME_MAX, "K8-%d", - i); - } - pcd->pcd_allocate_pmc = amd_allocate_pmc; pcd->pcd_config_pmc = amd_config_pmc; pcd->pcd_describe = amd_describe; @@ -870,16 +972,23 @@ pmc_amd_initialize(void) pcd->pcd_start_pmc = amd_start_pmc; pcd->pcd_stop_pmc = amd_stop_pmc; pcd->pcd_write_pmc = amd_write_pmc; + pcd->pcd_get_caps = amd_get_caps; pmc_mdep->pmd_cputype = cputype; pmc_mdep->pmd_intr = amd_intr; pmc_mdep->pmd_switch_in = amd_switch_in; pmc_mdep->pmd_switch_out = amd_switch_out; - pmc_mdep->pmd_npmc += AMD_NPMCS; + pmc_mdep->pmd_npmc += amd_npmcs; PMCDBG0(MDP, INI, 0, "amd-initialize"); + if (nclasses >= 3) { + error = pmc_ibs_initialize(pmc_mdep, ncpus); + if (error != 0) + goto error; + } + return (pmc_mdep); error: diff --git a/sys/dev/hwpmc/hwpmc_amd.h b/sys/dev/hwpmc/hwpmc_amd.h index d72fbc4878b6..6d8ab8203942 100644 --- a/sys/dev/hwpmc/hwpmc_amd.h +++ b/sys/dev/hwpmc/hwpmc_amd.h @@ -31,8 +31,12 @@ #ifndef _DEV_HWPMC_AMD_H_ #define _DEV_HWPMC_AMD_H_ 1 -/* AMD K8 PMCs */ +/* CPUIDs */ +#define CPUID_EXTPERFMON 0x80000022 +#define EXTPERFMON_CORE_PMCS(x) ((x) & 0x0F) +#define EXTPERFMON_DF_PMCS(x) (((x) >> 10) & 0x3F) +/* AMD K8 PMCs */ #define AMD_PMC_EVSEL_0 0xC0010000 #define AMD_PMC_EVSEL_1 0xC0010001 #define AMD_PMC_EVSEL_2 0xC0010002 @@ -42,42 +46,26 @@ #define AMD_PMC_PERFCTR_1 0xC0010005 #define AMD_PMC_PERFCTR_2 0xC0010006 #define AMD_PMC_PERFCTR_3 0xC0010007 -/* CORE */ -#define AMD_PMC_EVSEL_4 0xC0010208 -#define AMD_PMC_EVSEL_5 0xC001020A - -#define AMD_PMC_PERFCTR_4 0xC0010209 -#define AMD_PMC_PERFCTR_5 0xC001020B -/* L3 */ -#define AMD_PMC_EVSEL_EP_L3_0 0xC0010230 -#define AMD_PMC_EVSEL_EP_L3_1 0xC0010232 -#define AMD_PMC_EVSEL_EP_L3_2 0xC0010234 -#define AMD_PMC_EVSEL_EP_L3_3 0xC0010236 -#define AMD_PMC_EVSEL_EP_L3_4 0xC0010238 -#define AMD_PMC_EVSEL_EP_L3_5 0xC001023A - -#define AMD_PMC_PERFCTR_EP_L3_0 0xC0010231 -#define AMD_PMC_PERFCTR_EP_L3_1 0xC0010233 -#define AMD_PMC_PERFCTR_EP_L3_2 0xC0010235 -#define AMD_PMC_PERFCTR_EP_L3_3 0xC0010237 -#define AMD_PMC_PERFCTR_EP_L3_4 0xC0010239 -#define AMD_PMC_PERFCTR_EP_L3_5 0xC001023B -/* DF */ -#define AMD_PMC_EVSEL_EP_DF_0 0xC0010240 -#define AMD_PMC_EVSEL_EP_DF_1 0xC0010242 -#define AMD_PMC_EVSEL_EP_DF_2 0xC0010244 -#define AMD_PMC_EVSEL_EP_DF_3 0xC0010246 -#define AMD_PMC_PERFCTR_EP_DF_0 0xC0010241 -#define AMD_PMC_PERFCTR_EP_DF_1 0xC0010243 -#define AMD_PMC_PERFCTR_EP_DF_2 0xC0010245 -#define AMD_PMC_PERFCTR_EP_DF_3 0xC0010247 - -#define AMD_NPMCS 16 -#define AMD_CORE_NPMCS 6 +/* + * For older AMD processors we have hard coded the original four core counters. + * For newer processors we use the cpuid bits to setup the counter table. The + * counts below are the default number of registers assuming that you do not + * have CPUID leaf 0x80000022. The maximum number of counters is computed + * based on the available bits in the CPUID leaf and reserved MSR space. + * + * Refer to the PPRs for AMD Family 1Ah. + */ +/* CORE */ +#define AMD_PMC_CORE_BASE 0xC0010200 +#define AMD_PMC_CORE_DEFAULT 6 +#define AMD_PMC_CORE_MAX 16 #define AMD_PMC_COUNTERMASK 0xFF000000 +#define AMD_PMC_PRECISERETIRE (1ULL << 43) /* Only valid for PERF_CTL2 */ +#define AMD_PMC_HOST (1ULL << 41) +#define AMD_PMC_GUEST (1ULL << 40) #define AMD_PMC_TO_COUNTER(x) (((x) << 24) & AMD_PMC_COUNTERMASK) #define AMD_PMC_INVERT (1 << 23) #define AMD_PMC_ENABLE (1 << 22) @@ -86,24 +74,13 @@ #define AMD_PMC_EDGE (1 << 18) #define AMD_PMC_OS (1 << 17) #define AMD_PMC_USR (1 << 16) -#define AMD_PMC_L3SLICEMASK (0x000F000000000000) -#define AMD_PMC_L3COREMASK (0xFF00000000000000) -#define AMD_PMC_TO_L3SLICE(x) (((x) << 48) & AMD_PMC_L3SLICEMASK) -#define AMD_PMC_TO_L3CORE(x) (((x) << 56) & AMD_PMC_L3COREMASK) - -#define AMD_PMC_UNITMASK_M 0x10 -#define AMD_PMC_UNITMASK_O 0x08 -#define AMD_PMC_UNITMASK_E 0x04 -#define AMD_PMC_UNITMASK_S 0x02 -#define AMD_PMC_UNITMASK_I 0x01 -#define AMD_PMC_UNITMASK_MOESI 0x1F #define AMD_PMC_UNITMASK 0xFF00 #define AMD_PMC_EVENTMASK 0xF000000FF #define AMD_PMC_TO_UNITMASK(x) (((x) << 8) & AMD_PMC_UNITMASK) #define AMD_PMC_TO_EVENTMASK(x) (((x) & 0xFF) | (((uint64_t)(x) & 0xF00) << 24)) -#define AMD_PMC_TO_EVENTMASK_DF(x) (((x) & 0xFF) | (((uint64_t)(x) & 0x0F00) << 24)) | (((uint64_t)(x) & 0x3000) << 47) + #define AMD_VALID_BITS (AMD_PMC_COUNTERMASK | AMD_PMC_INVERT | \ AMD_PMC_ENABLE | AMD_PMC_INT | AMD_PMC_PC | AMD_PMC_EDGE | \ AMD_PMC_OS | AMD_PMC_USR | AMD_PMC_UNITMASK | AMD_PMC_EVENTMASK) @@ -112,13 +89,76 @@ PMC_CAP_SYSTEM | PMC_CAP_EDGE | PMC_CAP_THRESHOLD | \ PMC_CAP_READ | PMC_CAP_WRITE | PMC_CAP_INVERT | PMC_CAP_QUALIFIER) +/* L3 */ +#define AMD_PMC_L3_BASE 0xC0010230 +#define AMD_PMC_L3_DEFAULT 6 +#define AMD_PMC_L3_MAX 6 + +/* + * L3 counters change their encoding slightly between Family 17h and Family 19h + * processors. + * + * Refer to the following documents for the L3 fields: + * PPR for AMD Family 17h Model 20h A1 55772-A1 Rev. 3.08 April 14, 2021 + * PPR for AMD Family 19h Model 51h A1 56569-A1 Rev. 3.03 September 21, 2021 + * PPR for AMD Family 1Ah Model 02h C1 57238 Rev. 0.24 September 29, 2024 + */ +#define AMD_PMC_L31_SLICEMASK (0x000F000000000000ULL) +#define AMD_PMC_L31_COREMASK (0xFF00000000000000ULL) + +#define AMD_PMC_L31_TO_SLICE(x) (((uint64_t)(x) << 48) & AMD_PMC_L31_SLICEMASK) +#define AMD_PMC_L31_TO_CORE(x) (((uint64_t)(x) << 56) & AMD_PMC_L31_COREMASK) + +#define AMD_PMC_L32_THREADMASK (0x0F00000000000000ULL) +#define AMD_PMC_L32_SOURCEMASK (0x0007000000000000ULL) +#define AMD_PMC_L32_ALLCORES (1ULL << 47) +#define AMD_PMC_L32_ALLSOURCES (1ULL << 46) +#define AMD_PMC_L32_COREMASK (0x00001C0000000000ULL) + +#define AMD_PMC_L32_TO_THREAD(x) (((uint64_t)(x) << 56) & AMD_PMC_L32_THREADMASK) +#define AMD_PMC_L32_TO_SOURCEID(x) (((uint64_t)(x) << 48) & AMD_PMC_L32_SOURCEMASK) +#define AMD_PMC_L32_TO_COREID(x) (((uint64_t)(x) << 42) & AMD_PMC_L32_COREMASK) + +#define AMD_PMC_L3_TO_UNITMASK(x) (((x) << 8) & AMD_PMC_UNITMASK) +#define AMD_PMC_L3_TO_EVENTMASK(x) ((x) & 0xFF) + +#define AMD_PMC_L3_CAPS (PMC_CAP_READ | PMC_CAP_WRITE | \ + PMC_CAP_QUALIFIER | PMC_CAP_DOMWIDE) + +/* DF */ +#define AMD_PMC_DF_BASE 0xC0010240 +#define AMD_PMC_DF_DEFAULT 4 +#define AMD_PMC_DF_MAX 64 + +#define AMD_PMC_DF_CAPS (PMC_CAP_READ | PMC_CAP_WRITE | \ + PMC_CAP_QUALIFIER | PMC_CAP_DOMWIDE) + +/* + * DF counters change their encoding between Family 19h and Family 1Ah + * processors. + * + * Refer to the same documents as the L3 counters. + */ +#define AMD_PMC_DF1_TO_EVENTMASK(x) (((x) & 0xFF) | \ + (((uint64_t)(x) & 0x0F00) << 24) | (((uint64_t)(x) & 0x3000) << 47)) +#define AMD_PMC_DF1_TO_UNITMASK(x) (((x) & 0xFF) << 8) + +#define AMD_PMC_DF2_TO_EVENTMASK(x) (((x) & 0xFF) | \ + (((uint64_t)(x) & 0x7F00) << 24)) +#define AMD_PMC_DF2_TO_UNITMASK(x) ((((x) & 0xFF) << 8) | \ + (((uint64_t)(x) & 0x0F00) << 16)) + +#define AMD_NPMCS_K8 4 +#define AMD_NPMCS_MAX (AMD_PMC_CORE_MAX + AMD_PMC_L3_MAX + \ + AMD_PMC_DF_MAX) + #define AMD_PMC_IS_STOPPED(evsel) ((rdmsr((evsel)) & AMD_PMC_ENABLE) == 0) #define AMD_PMC_HAS_OVERFLOWED(pmc) ((rdpmc(pmc) & (1ULL << 47)) == 0) #define AMD_RELOAD_COUNT_TO_PERFCTR_VALUE(V) (-(V)) #define AMD_PERFCTR_VALUE_TO_RELOAD_COUNT(P) (-(P)) -enum sub_class{ +enum sub_class { PMC_AMD_SUB_CLASS_CORE, PMC_AMD_SUB_CLASS_L3_CACHE, PMC_AMD_SUB_CLASS_DATA_FABRIC diff --git a/sys/dev/hwpmc/hwpmc_arm64.c b/sys/dev/hwpmc/hwpmc_arm64.c index 310e43065716..794b285c0b3c 100644 --- a/sys/dev/hwpmc/hwpmc_arm64.c +++ b/sys/dev/hwpmc/hwpmc_arm64.c @@ -558,10 +558,9 @@ pmc_arm64_initialize(void) snprintf(pmc_cpuid, sizeof(pmc_cpuid), "0x%016lx", midr); /* Check if we have 64-bit counters */ - if (get_kernel_reg(ID_AA64DFR0_EL1, &dfr)) { - if (ID_AA64DFR0_PMUVer_VAL(dfr) >= ID_AA64DFR0_PMUVer_3_5) - arm64_64bit_events = true; - } + get_kernel_reg(ID_AA64DFR0_EL1, &dfr); + if (ID_AA64DFR0_PMUVer_VAL(dfr) >= ID_AA64DFR0_PMUVer_3_5) + arm64_64bit_events = true; /* * Allocate space for pointers to PMC HW descriptors and for diff --git a/sys/dev/hwpmc/hwpmc_ibs.c b/sys/dev/hwpmc/hwpmc_ibs.c new file mode 100644 index 000000000000..56903699ac51 --- /dev/null +++ b/sys/dev/hwpmc/hwpmc_ibs.c @@ -0,0 +1,643 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026, Netflix, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* Support for the AMD IBS */ + +#include <sys/param.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/pcpu.h> +#include <sys/pmc.h> +#include <sys/pmckern.h> +#include <sys/pmclog.h> +#include <sys/smp.h> +#include <sys/systm.h> + +#include <machine/cpu.h> +#include <machine/cpufunc.h> +#include <machine/md_var.h> +#include <machine/specialreg.h> + +#define IBS_STOP_ITER 50 /* Stopping iterations */ + +/* AMD IBS PMCs */ +struct ibs_descr { + struct pmc_descr pm_descr; /* "base class" */ +}; + +/* + * Globals + */ +static uint64_t ibs_features; + +/* + * Per-processor information + */ +#define IBS_CPU_RUNNING 1 +#define IBS_CPU_STOPPING 2 +#define IBS_CPU_STOPPED 3 + +struct ibs_cpu { + int pc_status; + struct pmc_hw pc_ibspmcs[IBS_NPMCS]; +}; +static struct ibs_cpu **ibs_pcpu; + +/* + * Read a PMC value from the MSR. + */ +static int +ibs_read_pmc(int cpu, int ri, struct pmc *pm, pmc_value_t *v) +{ + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[ibs,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < IBS_NPMCS, + ("[ibs,%d] illegal row-index %d", __LINE__, ri)); + KASSERT(ibs_pcpu[cpu], + ("[ibs,%d] null per-cpu, cpu %d", __LINE__, cpu)); + + /* read the IBS count */ + switch (ri) { + case IBS_PMC_FETCH: + *v = IBS_FETCH_CTL_TO_COUNT(rdmsr(IBS_FETCH_CTL)); + break; + case IBS_PMC_OP: + *v = IBS_OP_CTL_TO_COUNT(rdmsr(IBS_OP_CTL)); + break; + } + + PMCDBG2(MDP, REA, 2, "ibs-read id=%d -> %jd", ri, *v); + + return (0); +} + +/* + * Write a PMC MSR. + */ +static int +ibs_write_pmc(int cpu, int ri, struct pmc *pm, pmc_value_t v) +{ + pmc_value_t m; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[ibs,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < IBS_NPMCS, + ("[ibs,%d] illegal row-index %d", __LINE__, ri)); + + /* write the IBS count */ + switch (ri) { + case IBS_PMC_FETCH: + m = rdmsr(IBS_FETCH_CTL) & ~IBS_FETCH_CTL_CURCNTMASK; + /* Setting a count greater than interval is undefined. */ + if (IBS_FETCH_CTL_TO_INTERVAL(m) > v) + m |= IBS_FETCH_COUNT_TO_CTL(v); + wrmsr(IBS_FETCH_CTL, m); + break; + case IBS_PMC_OP: + m = rdmsr(IBS_OP_CTL) & ~IBS_OP_CTL_CURCNTMASK; + /* Setting a count greater than interval is undefined */ + if (IBS_OP_CTL_TO_INTERVAL(m) > v) + m |= IBS_OP_COUNT_TO_CTL(v); + wrmsr(IBS_OP_CTL, m); + break; + } + + PMCDBG3(MDP, WRI, 1, "ibs-write cpu=%d ri=%d v=%jx", cpu, ri, v); + + return (0); +} + +/* + * Configure hardware PMC according to the configuration recorded in 'pm'. + */ +static int +ibs_config_pmc(int cpu, int ri, struct pmc *pm) +{ + struct pmc_hw *phw; + + PMCDBG3(MDP, CFG, 1, "cpu=%d ri=%d pm=%p", cpu, ri, pm); + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[ibs,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < IBS_NPMCS, + ("[ibs,%d] illegal row-index %d", __LINE__, ri)); + + phw = &ibs_pcpu[cpu]->pc_ibspmcs[ri]; + + KASSERT(pm == NULL || phw->phw_pmc == NULL, + ("[ibs,%d] pm=%p phw->pm=%p hwpmc not unconfigured", + __LINE__, pm, phw->phw_pmc)); + + phw->phw_pmc = pm; + + return (0); +} + +/* + * Retrieve a configured PMC pointer from hardware state. + */ +static int +ibs_get_config(int cpu, int ri, struct pmc **ppm) +{ + + *ppm = ibs_pcpu[cpu]->pc_ibspmcs[ri].phw_pmc; + + return (0); +} + +/* + * Check if a given PMC allocation is feasible. + */ +static int +ibs_allocate_pmc(int cpu __unused, int ri, struct pmc *pm, + const struct pmc_op_pmcallocate *a) +{ + uint64_t caps, config; + + KASSERT(ri >= 0 && ri < IBS_NPMCS, + ("[ibs,%d] illegal row index %d", __LINE__, ri)); + + /* check class match */ + if (a->pm_class != PMC_CLASS_IBS) + return (EINVAL); + if (a->pm_md.pm_ibs.ibs_type != ri) + return (EINVAL); + + caps = pm->pm_caps; + + PMCDBG2(MDP, ALL, 1, "ibs-allocate ri=%d caps=0x%x", ri, caps); + + if ((caps & PMC_CAP_SYSTEM) == 0) + return (EINVAL); + + if (!PMC_IS_SAMPLING_MODE(a->pm_mode)) + return (EINVAL); + + config = a->pm_md.pm_ibs.ibs_ctl; + pm->pm_md.pm_ibs.ibs_ctl = config; + + PMCDBG2(MDP, ALL, 2, "ibs-allocate ri=%d -> config=0x%x", ri, config); + + return (0); +} + +/* + * Release machine dependent state associated with a PMC. This is a + * no-op on this architecture. + */ +static int +ibs_release_pmc(int cpu, int ri, struct pmc *pmc __unused) +{ + struct pmc_hw *phw __diagused; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[ibs,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < IBS_NPMCS, + ("[ibs,%d] illegal row-index %d", __LINE__, ri)); + + PMCDBG1(MDP, ALL, 1, "ibs-release ri=%d", ri); + + phw = &ibs_pcpu[cpu]->pc_ibspmcs[ri]; + + KASSERT(phw->phw_pmc == NULL, + ("[ibs,%d] PHW pmc %p non-NULL", __LINE__, phw->phw_pmc)); + + return (0); +} + +/* + * Start a PMC. + */ +static int +ibs_start_pmc(int cpu __diagused, int ri, struct pmc *pm) +{ + uint64_t config; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[ibs,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < IBS_NPMCS, + ("[ibs,%d] illegal row-index %d", __LINE__, ri)); + + PMCDBG2(MDP, STA, 1, "ibs-start cpu=%d ri=%d", cpu, ri); + + /* + * This is used to handle spurious NMIs. All that matters is that it + * is not in the stopping state. + */ + atomic_store_int(&ibs_pcpu[cpu]->pc_status, IBS_CPU_RUNNING); + + /* + * Turn on the ENABLE bit. Zeroing out the control register eliminates + * stale valid bits from spurious NMIs and it resets the counter. + */ + switch (ri) { + case IBS_PMC_FETCH: + wrmsr(IBS_FETCH_CTL, 0); + config = pm->pm_md.pm_ibs.ibs_ctl | IBS_FETCH_CTL_ENABLE; + wrmsr(IBS_FETCH_CTL, config); + break; + case IBS_PMC_OP: + wrmsr(IBS_OP_CTL, 0); + config = pm->pm_md.pm_ibs.ibs_ctl | IBS_OP_CTL_ENABLE; + wrmsr(IBS_OP_CTL, config); + break; + } + + return (0); +} + +/* + * Stop a PMC. + */ +static int +ibs_stop_pmc(int cpu __diagused, int ri, struct pmc *pm) +{ + int i; + uint64_t config; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[ibs,%d] illegal CPU value %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < IBS_NPMCS, + ("[ibs,%d] illegal row-index %d", __LINE__, ri)); + + PMCDBG1(MDP, STO, 1, "ibs-stop ri=%d", ri); + + /* + * Turn off the ENABLE bit, but unfortunately there are a few quirks + * that generate excess NMIs. Workaround #420 in the Revision Guide + * for AMD Family 10h Processors 41322 Rev. 3.92 March 2012. requires + * that we clear the max count before clearing enable. + * + * Even after clearing the counter spurious NMIs are still possible so + * we use a per-CPU atomic variable to notify the interrupt handler we + * are stopping and discard spurious NMIs. We then retry clearing the + * control register for 50us. This gives us enough time and ensures + * that the valid bit is not accidently stuck after a spurious NMI. + */ + config = pm->pm_md.pm_ibs.ibs_ctl; + + atomic_store_int(&ibs_pcpu[cpu]->pc_status, IBS_CPU_STOPPING); + + switch (ri) { + case IBS_PMC_FETCH: + wrmsr(IBS_FETCH_CTL, config & ~IBS_FETCH_CTL_MAXCNTMASK); + DELAY(1); + config &= ~IBS_FETCH_CTL_ENABLE; + wrmsr(IBS_FETCH_CTL, config); + break; + case IBS_PMC_OP: + wrmsr(IBS_OP_CTL, config & ~IBS_OP_CTL_MAXCNTMASK); + DELAY(1); + config &= ~IBS_OP_CTL_ENABLE; + wrmsr(IBS_OP_CTL, config); + break; + } + + for (i = 0; i < IBS_STOP_ITER; i++) { + DELAY(1); + + switch (ri) { + case IBS_PMC_FETCH: + wrmsr(IBS_FETCH_CTL, 0); + break; + case IBS_PMC_OP: + wrmsr(IBS_OP_CTL, 0); + break; + } + } + + atomic_store_int(&ibs_pcpu[cpu]->pc_status, IBS_CPU_STOPPED); + + return (0); +} + +static void +pmc_ibs_process_fetch(struct pmc *pm, struct trapframe *tf, uint64_t config) +{ + struct pmc_multipart mpd; + + if (pm == NULL) + return; + + if (pm->pm_state != PMC_STATE_RUNNING) + return; + + memset(&mpd, 0, sizeof(mpd)); + + mpd.pl_type = PMC_CC_MULTIPART_IBS_FETCH; + mpd.pl_length = PMC_MPIDX_FETCH_MAX; + mpd.pl_mpdata[PMC_MPIDX_FETCH_CTL] = config; + if ((ibs_features & CPUID_IBSID_IBSFETCHCTLEXTD) != 0) { + mpd.pl_mpdata[PMC_MPIDX_FETCH_EXTCTL] = rdmsr(IBS_FETCH_EXTCTL); + } + mpd.pl_mpdata[PMC_MPIDX_FETCH_CTL] = config; + mpd.pl_mpdata[PMC_MPIDX_FETCH_LINADDR] = rdmsr(IBS_FETCH_LINADDR); + if ((config & IBS_FETCH_CTL_PHYSADDRVALID) != 0) { + mpd.pl_mpdata[PMC_MPIDX_FETCH_PHYSADDR] = + rdmsr(IBS_FETCH_PHYSADDR); + } + + pmc_process_interrupt_mp(PMC_HR, pm, tf, &mpd); + + wrmsr(IBS_FETCH_CTL, pm->pm_md.pm_ibs.ibs_ctl | IBS_FETCH_CTL_ENABLE); +} + +static void +pmc_ibs_process_op(struct pmc *pm, struct trapframe *tf, uint64_t config) +{ + struct pmc_multipart mpd; + + if (pm == NULL) + return; + + if (pm->pm_state != PMC_STATE_RUNNING) + return; + + memset(&mpd, 0, sizeof(mpd)); + + mpd.pl_type = PMC_CC_MULTIPART_IBS_OP; + mpd.pl_length = PMC_MPIDX_OP_MAX; + mpd.pl_mpdata[PMC_MPIDX_OP_CTL] = config; + mpd.pl_mpdata[PMC_MPIDX_OP_RIP] = rdmsr(IBS_OP_RIP); + mpd.pl_mpdata[PMC_MPIDX_OP_DATA] = rdmsr(IBS_OP_DATA); + mpd.pl_mpdata[PMC_MPIDX_OP_DATA2] = rdmsr(IBS_OP_DATA2); + mpd.pl_mpdata[PMC_MPIDX_OP_DATA3] = rdmsr(IBS_OP_DATA3); + mpd.pl_mpdata[PMC_MPIDX_OP_DC_LINADDR] = rdmsr(IBS_OP_DC_LINADDR); + mpd.pl_mpdata[PMC_MPIDX_OP_DC_PHYSADDR] = rdmsr(IBS_OP_DC_PHYSADDR); + if ((ibs_features & CPUID_IBSID_BRNTRGT) != 0) { + mpd.pl_mpdata[PMC_MPIDX_OP_TGT_RIP] = rdmsr(IBS_OP_TGT_RIP); + } + if ((ibs_features & CPUID_IBSID_IBSOPDATA4) != 0) { + mpd.pl_mpdata[PMC_MPIDX_OP_DATA4] = rdmsr(IBS_OP_DATA4); + } + + pmc_process_interrupt_mp(PMC_HR, pm, tf, &mpd); + + wrmsr(IBS_OP_CTL, pm->pm_md.pm_ibs.ibs_ctl | IBS_OP_CTL_ENABLE); +} + +/* + * Interrupt handler. This function needs to return '1' if the + * interrupt was this CPU's PMCs or '0' otherwise. It is not allowed + * to sleep or do anything a 'fast' interrupt handler is not allowed + * to do. + */ +int +pmc_ibs_intr(struct trapframe *tf) +{ + struct ibs_cpu *pac; + struct pmc *pm; + int retval, cpu; + uint64_t config; + + cpu = curcpu; + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[ibs,%d] out of range CPU %d", __LINE__, cpu)); + + PMCDBG3(MDP, INT, 1, "cpu=%d tf=%p um=%d", cpu, tf, TRAPF_USERMODE(tf)); + + retval = 0; + + pac = ibs_pcpu[cpu]; + + config = rdmsr(IBS_FETCH_CTL); + if ((config & IBS_FETCH_CTL_VALID) != 0) { + pm = pac->pc_ibspmcs[IBS_PMC_FETCH].phw_pmc; + + retval = 1; + + pmc_ibs_process_fetch(pm, tf, config); + } + + config = rdmsr(IBS_OP_CTL); + if ((retval == 0) && ((config & IBS_OP_CTL_VALID) != 0)) { + pm = pac->pc_ibspmcs[IBS_PMC_OP].phw_pmc; + + retval = 1; + + pmc_ibs_process_op(pm, tf, config); + } + + if (retval == 0) { + // Lets check for a stray NMI when stopping + if (atomic_load_int(&pac->pc_status) == IBS_CPU_STOPPING) { + return (1); + } + } + + + if (retval) + counter_u64_add(pmc_stats.pm_intr_processed, 1); + else + counter_u64_add(pmc_stats.pm_intr_ignored, 1); + + PMCDBG1(MDP, INT, 2, "retval=%d", retval); + + return (retval); +} + +/* + * Describe a PMC. + */ +static int +ibs_describe(int cpu, int ri, struct pmc_info *pi, struct pmc **ppmc) +{ + struct pmc_hw *phw; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[ibs,%d] illegal CPU %d", __LINE__, cpu)); + KASSERT(ri >= 0 && ri < IBS_NPMCS, + ("[ibs,%d] row-index %d out of range", __LINE__, ri)); + + phw = &ibs_pcpu[cpu]->pc_ibspmcs[ri]; + + if (ri == IBS_PMC_FETCH) { + strlcpy(pi->pm_name, "IBS-FETCH", sizeof(pi->pm_name)); + pi->pm_class = PMC_CLASS_IBS; + pi->pm_enabled = true; + *ppmc = phw->phw_pmc; + } else { + strlcpy(pi->pm_name, "IBS-OP", sizeof(pi->pm_name)); + pi->pm_class = PMC_CLASS_IBS; + pi->pm_enabled = true; + *ppmc = phw->phw_pmc; + } + + return (0); +} + +/* + * Processor-dependent initialization. + */ +static int +ibs_pcpu_init(struct pmc_mdep *md, int cpu) +{ + struct ibs_cpu *pac; + struct pmc_cpu *pc; + struct pmc_hw *phw; + int first_ri, n; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[ibs,%d] insane cpu number %d", __LINE__, cpu)); + + PMCDBG1(MDP, INI, 1, "ibs-init cpu=%d", cpu); + + ibs_pcpu[cpu] = pac = malloc(sizeof(struct ibs_cpu), M_PMC, + M_WAITOK | M_ZERO); + + /* + * Set the content of the hardware descriptors to a known + * state and initialize pointers in the MI per-cpu descriptor. + */ + pc = pmc_pcpu[cpu]; + first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IBS].pcd_ri; + + KASSERT(pc != NULL, ("[ibs,%d] NULL per-cpu pointer", __LINE__)); + + for (n = 0, phw = pac->pc_ibspmcs; n < IBS_NPMCS; n++, phw++) { + phw->phw_state = PMC_PHW_FLAG_IS_ENABLED | + PMC_PHW_CPU_TO_STATE(cpu) | PMC_PHW_INDEX_TO_STATE(n); + phw->phw_pmc = NULL; + pc->pc_hwpmcs[n + first_ri] = phw; + } + + return (0); +} + +/* + * Processor-dependent cleanup prior to the KLD being unloaded. + */ +static int +ibs_pcpu_fini(struct pmc_mdep *md, int cpu) +{ + struct ibs_cpu *pac; + struct pmc_cpu *pc; + int first_ri, i; + + KASSERT(cpu >= 0 && cpu < pmc_cpu_max(), + ("[ibs,%d] insane cpu number (%d)", __LINE__, cpu)); + + PMCDBG1(MDP, INI, 1, "ibs-cleanup cpu=%d", cpu); + + /* + * Turn off IBS. + */ + wrmsr(IBS_FETCH_CTL, 0); + wrmsr(IBS_OP_CTL, 0); + + /* + * Free up allocated space. + */ + if ((pac = ibs_pcpu[cpu]) == NULL) + return (0); + + ibs_pcpu[cpu] = NULL; + + pc = pmc_pcpu[cpu]; + KASSERT(pc != NULL, ("[ibs,%d] NULL per-cpu state", __LINE__)); + + first_ri = md->pmd_classdep[PMC_MDEP_CLASS_INDEX_IBS].pcd_ri; + + /* + * Reset pointers in the MI 'per-cpu' state. + */ + for (i = 0; i < IBS_NPMCS; i++) + pc->pc_hwpmcs[i + first_ri] = NULL; + + free(pac, M_PMC); + + return (0); +} + +/* + * Initialize ourselves. + */ +int +pmc_ibs_initialize(struct pmc_mdep *pmc_mdep, int ncpus) +{ + u_int regs[4]; + struct pmc_classdep *pcd; + + /* + * Allocate space for pointers to PMC HW descriptors and for + * the MDEP structure used by MI code. + */ + ibs_pcpu = malloc(sizeof(struct ibs_cpu *) * pmc_cpu_max(), M_PMC, + M_WAITOK | M_ZERO); + + /* Initialize AMD IBS handling. */ + pcd = &pmc_mdep->pmd_classdep[PMC_MDEP_CLASS_INDEX_IBS]; + + pcd->pcd_caps = IBS_PMC_CAPS; + pcd->pcd_class = PMC_CLASS_IBS; + pcd->pcd_num = IBS_NPMCS; + pcd->pcd_ri = pmc_mdep->pmd_npmc; + pcd->pcd_width = 0; + + pcd->pcd_allocate_pmc = ibs_allocate_pmc; + pcd->pcd_config_pmc = ibs_config_pmc; + pcd->pcd_describe = ibs_describe; + pcd->pcd_get_config = ibs_get_config; + pcd->pcd_pcpu_fini = ibs_pcpu_fini; + pcd->pcd_pcpu_init = ibs_pcpu_init; + pcd->pcd_release_pmc = ibs_release_pmc; + pcd->pcd_start_pmc = ibs_start_pmc; + pcd->pcd_stop_pmc = ibs_stop_pmc; + pcd->pcd_read_pmc = ibs_read_pmc; + pcd->pcd_write_pmc = ibs_write_pmc; + + pmc_mdep->pmd_npmc += IBS_NPMCS; + + if (cpu_exthigh >= CPUID_IBSID) { + do_cpuid(CPUID_IBSID, regs); + ibs_features = regs[0]; + } else { + ibs_features = 0; + } + + PMCDBG0(MDP, INI, 0, "ibs-initialize"); + + return (0); +} + +/* + * Finalization code for AMD CPUs. + */ +void +pmc_ibs_finalize(struct pmc_mdep *md) +{ + PMCDBG0(MDP, INI, 1, "ibs-finalize"); + + for (int i = 0; i < pmc_cpu_max(); i++) + KASSERT(ibs_pcpu[i] == NULL, + ("[ibs,%d] non-null pcpu cpu %d", __LINE__, i)); + + free(ibs_pcpu, M_PMC); + ibs_pcpu = NULL; +} diff --git a/sys/dev/hwpmc/hwpmc_ibs.h b/sys/dev/hwpmc/hwpmc_ibs.h new file mode 100644 index 000000000000..2b4e111ba171 --- /dev/null +++ b/sys/dev/hwpmc/hwpmc_ibs.h @@ -0,0 +1,203 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026, Netflix, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _DEV_HWPMC_IBS_H_ +#define _DEV_HWPMC_IBS_H_ 1 + +#define IBS_NPMCS 2 +#define IBS_PMC_FETCH 0 +#define IBS_PMC_OP 1 + +/* + * All of the CPUID definitions come from AMD PPR Vol 1 for AMD Family 1Ah + * Model 02h C1 (57238) 2024-09-29 Revision 0.24. + */ +#define CPUID_IBSID 0x8000001B +#define CPUID_IBSID_IBSFFV 0x00000001 /* IBS Feature Flags Valid */ +#define CPUID_IBSID_FETCHSAM 0x00000002 /* IBS Fetch Sampling */ +#define CPUID_IBSID_OPSAM 0x00000004 /* IBS Execution Sampling */ +#define CPUID_IBSID_RDWROPCNT 0x00000008 /* RdWr Operationg Counter */ +#define CPUID_IBSID_OPCNT 0x00000010 /* Operation Counter */ +#define CPUID_IBSID_BRNTRGT 0x00000020 /* Branch Target Address */ +#define CPUID_IBSID_OPCNTEXT 0x00000040 /* Extend Counter */ +#define CPUID_IBSID_RIPINVALIDCHK 0x00000080 /* Invalid RIP Indication */ +#define CPUID_IBSID_OPFUSE 0x00000100 /* Fused Branch Operation */ +#define CPUID_IBSID_IBSFETCHCTLEXTD 0x00000200 /* IBS Fetch Control Ext */ +#define CPUID_IBSID_IBSOPDATA4 0x00000400 /* IBS OP DATA4 */ +#define CPUID_IBSID_ZEN4IBSEXTENSIONS 0x00000800 /* IBS Zen 4 Extensions */ +#define CPUID_IBSID_IBSLOADLATENCYFILT 0x00001000 /* Load Latency Filtering */ +#define CPUID_IBSID_IBSUPDTDDTLBSTATS 0x00080000 /* Simplified DTLB Stats */ + +/* + * All of these definitions here come from AMD64 Architecture Programmer's + * Manual Volume 2: System Programming (24593) 2025-07-02 Version 3.43. with + * the following exceptions: + * + * OpData4 and fields come from the BKDG for AMD Family 15h Model 70-7Fh + * (55072) 2018-06-20 Revision 3.09. + */ + +/* IBS MSRs */ +#define IBS_CTL 0xC001103A /* IBS Control */ +#define IBS_CTL_LVTOFFSETVALID (1ULL << 8) +#define IBS_CTL_LVTOFFSETMASK 0x0000000F + +/* + * The minimum sampling rate was selected to match the default used by other + * counters that was also found to be experimentally stable by providing enough + * time between consecutive NMIs. The maximum sample rate is determined by + * setting all available counter bits, i.e., all available bits except the + * bottom four that are zero extended. + */ +#define IBS_FETCH_MIN_RATE 65536 +#define IBS_FETCH_MAX_RATE 1048560 +#define IBS_OP_MIN_RATE 65536 +#define IBS_OP_MAX_RATE 134217712 +#define IBS_OP_MAX_RATE_PREEXT 1048560 + +/* IBS Fetch Control */ +#define IBS_FETCH_CTL 0xC0011030 /* IBS Fetch Control */ +#define IBS_FETCH_CTL_L3MISS (1ULL << 61) /* L3 Cache Miss */ +#define IBS_FETCH_CTL_OPCACHEMISS (1ULL << 60) /* Op Cache Miss */ +#define IBS_FETCH_CTL_L3MISSONLY (1ULL << 59) /* L3 Miss Filtering */ +#define IBS_FETCH_CTL_RANDOMIZE (1ULL << 57) /* Randomized Tagging */ +#define IBS_FETCH_CTL_L1TLBMISS (1ULL << 55) /* L1 TLB Miss */ +// Page size 54:53 +#define IBS_FETCH_CTL_PHYSADDRVALID (1ULL << 52) /* PHYSADDR Valid */ +#define IBS_FETCH_CTL_ICMISS (1ULL << 51) /* Inst. Cache Miss */ +#define IBS_FETCH_CTL_COMPLETE (1ULL << 50) /* Complete */ +#define IBS_FETCH_CTL_VALID (1ULL << 49) /* Valid */ +#define IBS_FETCH_CTL_ENABLE (1ULL << 48) /* Enable */ +#define IBS_FETCH_CTL_MAXCNTMASK 0x0000FFFFULL +#define IBS_FETCH_CTL_CURCNTMASK 0xFFFF0000ULL + +#define IBS_FETCH_INTERVAL_TO_CTL(_c) (((_c) >> 4) & 0x0000FFFF) +#define IBS_FETCH_CTL_TO_INTERVAL(_c) (((_c) & IBS_FETCH_CTL_MAXCNTMASK) << 4) +#define IBS_FETCH_CTL_TO_LAT(_c) (((_c) >> 32) & 0x0000FFFF) +#define IBS_FETCH_COUNT_TO_CTL(_c) (((_c) << 12) & IBS_FETCH_CTL_CURCNTMASK) +#define IBS_FETCH_CTL_TO_COUNT(_c) (((_c) & IBS_FETCH_CTL_CURCNTMASK) >> 12) + +#define IBS_FETCH_LINADDR 0xC0011031 /* Fetch Linear Address */ +#define IBS_FETCH_PHYSADDR 0xC0011032 /* Fetch Physical Address */ +#define IBS_FETCH_EXTCTL 0xC001103C /* Fetch Control Extended */ + +#define PMC_MPIDX_FETCH_CTL 0 +#define PMC_MPIDX_FETCH_EXTCTL 1 +#define PMC_MPIDX_FETCH_LINADDR 2 +#define PMC_MPIDX_FETCH_PHYSADDR 3 +#define PMC_MPIDX_FETCH_MAX (PMC_MPIDX_FETCH_PHYSADDR + 1) + +/* IBS Execution Control */ +#define IBS_OP_CTL 0xC0011033 /* IBS Execution Control */ +#define IBS_OP_CTL_LATFLTEN (1ULL << 63) /* Load Latency Filtering */ +#define IBS_OP_CTL_COUNTERCONTROL (1ULL << 19) /* Counter Control */ +#define IBS_OP_CTL_VALID (1ULL << 18) /* Valid */ +#define IBS_OP_CTL_ENABLE (1ULL << 17) /* Enable */ +#define IBS_OP_CTL_L3MISSONLY (1ULL << 16) /* L3 Miss Filtering */ +#define IBS_OP_CTL_MAXCNTMASK 0x07F0FFFFULL +#define IBS_OP_CTL_CURCNTMASK 0x07FFFFFF00000000ULL + +#define IBS_OP_CTL_LDLAT_TO_CTL(_c) ((((ldlat) >> 7) - 1) << 59) +#define IBS_OP_INTERVAL_TO_CTL(_c) ((((_c) >> 4) & 0x0000FFFFULL) | ((_c) & 0x07F00000)) +#define IBS_OP_CTL_TO_INTERVAL(_c) ((((_c) & 0x0000FFFFULL) << 4) | ((_c) & 0x07F00000)) +#define IBS_OP_COUNT_TO_CTL(_c) (((_c) << 32) & IBS_OP_CTL_CURCNTMASK) +#define IBS_OP_CTL_TO_COUNT(_c) (((_c) & IBS_OP_CTL_CURCNTMASK) >> 32) + +#define IBS_OP_RIP 0xC0011034 /* IBS Op RIP */ +#define IBS_OP_DATA 0xC0011035 /* IBS Op Data */ +#define IBS_OP_DATA_RIPINVALID (1ULL << 38) /* RIP Invalid */ +#define IBS_OP_DATA_BRANCHRETIRED (1ULL << 37) /* Branch Retired */ +#define IBS_OP_DATA_BRANCHMISPREDICTED (1ULL << 36) /* Branch Mispredicted */ +#define IBS_OP_DATA_BRANCHTAKEN (1ULL << 35) /* Branch Taken */ +#define IBS_OP_DATA_RETURN (1ULL << 34) /* Return */ + +#define IBS_OP_DATA2 0xC0011036 /* IBS Op Data 2 */ +#define IBS_OP_DATA3 0xC0011037 /* IBS Op Data 3 */ +#define IBS_OP_DATA3_DCPHYADDRVALID (1ULL << 18) /* DC Physical Address */ +#define IBS_OP_DATA3_DCLINADDRVALID (1ULL << 17) /* DC Linear Address */ +#define IBS_OP_DATA3_LOCKEDOP (1ULL << 15) /* DC Locked Op */ +#define IBS_OP_DATA3_UCMEMACCESS (1ULL << 14) /* DC UC Memory Access */ +#define IBS_OP_DATA3_WCMEMACCESS (1ULL << 13) /* DC WC Memory Access */ +#define IBS_OP_DATA3_DCMISALIGN (1ULL << 8) /* DC Misaligned Access */ +#define IBS_OP_DATA3_DCMISS (1ULL << 7) /* DC Miss */ +#define IBS_OP_DATA3_DCL1TLBHIT1G (1ULL << 5) /* DC L1 TLB Hit 1-GB */ +#define IBS_OP_DATA3_DCL1TLBHIT2M (1ULL << 4) /* DC L1 TLB Hit 2-MB */ +#define IBS_OP_DATA3_DCL1TLBMISS (1ULL << 2) /* DC L1 TLB Miss */ +#define IBS_OP_DATA3_STORE (1ULL << 1) /* Store */ +#define IBS_OP_DATA3_LOAD (1ULL << 0) /* Load */ +#define IBS_OP_DATA3_TO_DCLAT(_c) ((_c >> 32) & 0x0000FFFF) + +#define IBS_OP_DC_LINADDR 0xC0011038 /* IBS DC Linear Address */ +#define IBS_OP_DC_PHYSADDR 0xC0011039 /* IBS DC Physical Address */ +#define IBS_OP_TGT_RIP 0xC001103B /* IBS Branch Target */ +#define IBS_OP_DATA4 0xC001103D /* IBS Op Data 4 */ +#define IBS_OP_DATA4_LDRESYNC (1ULL << 0) /* Load Resync */ + +#define PMC_MPIDX_OP_CTL 0 +#define PMC_MPIDX_OP_RIP 1 +#define PMC_MPIDX_OP_DATA 2 +#define PMC_MPIDX_OP_DATA2 3 +#define PMC_MPIDX_OP_DATA3 4 +#define PMC_MPIDX_OP_DC_LINADDR 5 +#define PMC_MPIDX_OP_DC_PHYSADDR 6 +#define PMC_MPIDX_OP_TGT_RIP 7 +#define PMC_MPIDX_OP_DATA4 8 +#define PMC_MPIDX_OP_MAX (PMC_MPIDX_OP_DATA4 + 1) + +/* + * IBS data is encoded as using the multipart flag in the existing callchain + * structure. The PMC ID number tells you if the sample contains a fetch or an + * op sample. The available payload will be encoded in the MSR order with a + * variable length. + */ + +struct pmc_md_ibs_op_pmcallocate { + uint32_t ibs_flag; + uint32_t ibs_type; + uint64_t ibs_ctl; + uint64_t ibs_ctl2; +}; + +#ifdef _KERNEL + +/* MD extension for 'struct pmc' */ +struct pmc_md_ibs_pmc { + uint32_t ibs_flag; + uint32_t ibs_type; + uint64_t ibs_ctl; + uint64_t ibs_ctl2; +}; + +#define IBS_PMC_CAPS (PMC_CAP_INTERRUPT | PMC_CAP_SYSTEM | \ + PMC_CAP_EDGE | PMC_CAP_QUALIFIER | PMC_CAP_PRECISE) + +int pmc_ibs_initialize(struct pmc_mdep *md, int ncpu); +void pmc_ibs_finalize(struct pmc_mdep *md); +int pmc_ibs_intr(struct trapframe *tf); + +#endif /* _KERNEL */ +#endif /* _DEV_HWPMC_IBS_H_ */ diff --git a/sys/dev/hwpmc/hwpmc_intel.c b/sys/dev/hwpmc/hwpmc_intel.c index 6d8b5c5de6b6..942cadfae4cf 100644 --- a/sys/dev/hwpmc/hwpmc_intel.c +++ b/sys/dev/hwpmc/hwpmc_intel.c @@ -247,6 +247,17 @@ pmc_intel_initialize(void) cputype = PMC_CPU_INTEL_ATOM_TREMONT; nclasses = 3; break; + case 0xAA: + case 0xAC: + case 0xB5: + cputype = PMC_CPU_INTEL_METEOR_LAKE; + nclasses = 3; + break; + case 0xAD: + case 0xAE: + cputype = PMC_CPU_INTEL_GRANITE_RAPIDS; + nclasses = 3; + break; case 0xBE: cputype = PMC_CPU_INTEL_ALDERLAKEN; nclasses = 3; diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c index 8fd7ef06a977..4f507523b6ab 100644 --- a/sys/dev/hwpmc/hwpmc_logging.c +++ b/sys/dev/hwpmc/hwpmc_logging.c @@ -58,6 +58,7 @@ #include <sys/uio.h> #include <sys/unistd.h> #include <sys/vnode.h> +#include <sys/syslog.h> #if defined(__i386__) || defined(__amd64__) #include <machine/clock.h> @@ -1236,24 +1237,39 @@ pmclog_initialize(void) struct pmclog_buffer *plb; int domain, ncpus, total; - if (pmclog_buffer_size <= 0 || pmclog_buffer_size > 16*1024) { - (void) printf("hwpmc: tunable logbuffersize=%d must be " - "greater than zero and less than or equal to 16MB.\n", - pmclog_buffer_size); + if (pmclog_buffer_size <= 0 || + pmclog_buffer_size > PMC_LOG_BUFFER_SIZE_MAX) { + log(LOG_WARNING, + "hwpmc: logbuffersize=%d must be greater than zero " + "and less than or equal to %d, resetting to %d\n", + pmclog_buffer_size, PMC_LOG_BUFFER_SIZE_MAX, + PMC_LOG_BUFFER_SIZE); + pmclog_buffer_size = PMC_LOG_BUFFER_SIZE; } if (pmc_nlogbuffers_pcpu <= 0) { - (void) printf("hwpmc: tunable nlogbuffers=%d must be greater " - "than zero.\n", pmc_nlogbuffers_pcpu); + log(LOG_WARNING, + "hwpmc: nbuffers_pcpu=%d must be greater than zero, " + "resetting to %d\n", + pmc_nlogbuffers_pcpu, PMC_NLOGBUFFERS_PCPU); + pmc_nlogbuffers_pcpu = PMC_NLOGBUFFERS_PCPU; } - if (pmc_nlogbuffers_pcpu*pmclog_buffer_size > 32*1024) { - (void) printf("hwpmc: memory allocated pcpu must be less than 32MB (is %dK).\n", - pmc_nlogbuffers_pcpu*pmclog_buffer_size); + + if (pmc_nlogbuffers_pcpu * pmclog_buffer_size > + PMC_NLOGBUFFERS_PCPU_MEM_MAX) { + log(LOG_WARNING, + "hwpmc: nbuffers_pcpu=%d * logbuffersize=%d exceeds " + "%dMB per CPU limit, resetting to defaults (%d * %d)\n", + pmc_nlogbuffers_pcpu, pmclog_buffer_size, + PMC_NLOGBUFFERS_PCPU_MEM_MAX / 1024, + PMC_NLOGBUFFERS_PCPU, PMC_LOG_BUFFER_SIZE); + pmc_nlogbuffers_pcpu = PMC_NLOGBUFFERS_PCPU; pmclog_buffer_size = PMC_LOG_BUFFER_SIZE; } + for (domain = 0; domain < vm_ndomains; domain++) { ncpus = pmc_dom_hdrs[domain]->pdbh_ncpus; total = ncpus * pmc_nlogbuffers_pcpu; @@ -1270,6 +1286,7 @@ pmclog_initialize(void) pmc_plb_rele_unlocked(plb); } } + mtx_init(&pmc_kthread_mtx, "pmc-kthread", "pmc-sleep", MTX_DEF); } diff --git a/sys/dev/hwpmc/hwpmc_mod.c b/sys/dev/hwpmc/hwpmc_mod.c index a6a6ae68996c..9533cb81b4a1 100644 --- a/sys/dev/hwpmc/hwpmc_mod.c +++ b/sys/dev/hwpmc/hwpmc_mod.c @@ -198,9 +198,14 @@ static int pmc_debugflags_sysctl_handler(SYSCTL_HANDLER_ARGS); static int pmc_debugflags_parse(char *newstr, char *fence); #endif +static void pmc_multipart_add(struct pmc_sample *ps, int type, + int length); +static void pmc_multipart_copydata(struct pmc_sample *ps, + struct pmc_multipart *mp); + static int load(struct module *module, int cmd, void *arg); static int pmc_add_sample(ring_type_t ring, struct pmc *pm, - struct trapframe *tf); + struct trapframe *tf, struct pmc_multipart *mp); static void pmc_add_thread_descriptors_from_proc(struct proc *p, struct pmc_process *pp); static int pmc_attach_process(struct proc *p, struct pmc *pm); @@ -812,11 +817,9 @@ pmc_force_context_switch(void) uint64_t pmc_rdtsc(void) { -#if defined(__i386__) || defined(__amd64__) - if (__predict_true(amd_feature & AMDID_RDTSCP)) - return (rdtscp()); - else - return (rdtsc()); +#if defined(__i386__) + /* Unfortunately get_cyclecount on i386 uses cpu_ticks. */ + return (rdtsc()); #else return (get_cyclecount()); #endif @@ -4532,6 +4535,51 @@ pmc_syscall_handler(struct thread *td, void *syscall_args) } break; + /* + * Get the PMC capabilities + */ + + case PMC_OP_GETCAPS: + { + struct pmc_op_caps c; + struct pmc *pm; + struct pmc_classdep *pcd; + pmc_id_t pmcid; + int adjri, ri; + + PMC_DOWNGRADE_SX(); + + if ((error = copyin(arg, &c, sizeof(c))) != 0) + break; + + pmcid = c.pm_pmcid; + + if ((error = pmc_find_pmc(pmcid, &pm)) != 0) + break; + + KASSERT(pmcid == pm->pm_id, + ("[pmc,%d] pmc id %x != pmcid %x", __LINE__, + pm->pm_id, pmcid)); + + ri = PMC_TO_ROWINDEX(pm); + pcd = pmc_ri_to_classdep(md, ri, &adjri); + + /* + * If PMC class has no GETCAPS return the class capabilities + * otherwise get the per counter capabilities. + */ + if (pcd->pcd_get_caps == NULL) { + c.pm_caps = pcd->pcd_caps; + } else { + error = (*pcd->pcd_get_caps)(adjri, &c.pm_caps); + if (error < 0) + break; + } + + if ((error = copyout(&c, arg, sizeof(c))) < 0) + break; + } + break; default: error = EINVAL; @@ -4587,6 +4635,47 @@ pmc_post_callchain_callback(void) return; } +static void +pmc_multipart_add(struct pmc_sample *ps, int type, int length) +{ + int i; + uint8_t *hdr; + + MPASS(ps->ps_pc != NULL); + MPASS(ps->ps_nsamples_actual != 0); + + hdr = (uint8_t *)ps->ps_pc; + + for (i = 0; i < PMC_MULTIPART_HEADER_ENTRIES; i++) { + if (hdr[2 * i] == PMC_CC_MULTIPART_NONE) { + hdr[2 * i] = type; + hdr[2 * i + 1] = length; + ps->ps_nsamples_actual += length; + return; + } + } + + KASSERT(false, ("Too many parts in the multipart header!")); +} + +static void +pmc_multipart_copydata(struct pmc_sample *ps, struct pmc_multipart *mp) +{ + int i, scale; + uint64_t *ps_pc; + + MPASS(ps->ps_pc != NULL); + MPASS(ps->ps_nsamples_actual != 0); + + ps_pc = (uint64_t *)ps->ps_pc; + + for (i = 0; i < mp->pl_length; i++) + ps_pc[i + 1] = mp->pl_mpdata[i]; + + scale = sizeof(uint64_t) / sizeof(uintptr_t); + pmc_multipart_add(ps, mp->pl_type, scale * mp->pl_length); +} + /* * Find a free slot in the per-cpu array of samples and capture the * current callchain there. If a sample was successfully added, a bit @@ -4597,7 +4686,8 @@ pmc_post_callchain_callback(void) * use any of the locking primitives supplied by the OS. */ static int -pmc_add_sample(ring_type_t ring, struct pmc *pm, struct trapframe *tf) +pmc_add_sample(ring_type_t ring, struct pmc *pm, struct trapframe *tf, + struct pmc_multipart *mp) { struct pmc_sample *ps; struct pmc_samplebuffer *psb; @@ -4641,21 +4731,33 @@ pmc_add_sample(ring_type_t ring, struct pmc *pm, struct trapframe *tf) ps->ps_ticks = ticks; ps->ps_cpu = cpu; ps->ps_flags = inuserspace ? PMC_CC_F_USERSPACE : 0; + ps->ps_nsamples_actual = 0; callchaindepth = (pm->pm_flags & PMC_F_CALLCHAIN) ? pmc_callchaindepth : 1; MPASS(ps->ps_pc != NULL); + + if (mp != NULL) { + /* Set multipart flag, clear header and copy data */ + ps->ps_flags |= PMC_CC_F_MULTIPART; + ps->ps_pc[0] = 0; + ps->ps_nsamples_actual = 1; + pmc_multipart_copydata(ps, mp); + } + if (callchaindepth == 1) { - ps->ps_pc[0] = PMC_TRAPFRAME_TO_PC(tf); + ps->ps_pc[ps->ps_nsamples_actual] = PMC_TRAPFRAME_TO_PC(tf); } else { /* * Kernel stack traversals can be done immediately, while we * defer to an AST for user space traversals. */ if (!inuserspace) { - callchaindepth = pmc_save_kernel_callchain(ps->ps_pc, - callchaindepth, tf); + callchaindepth = pmc_save_kernel_callchain( + ps->ps_pc + ps->ps_nsamples_actual, + callchaindepth - ps->ps_nsamples_actual, tf); + callchaindepth += ps->ps_nsamples_actual; } else { pmc_post_callchain_callback(); callchaindepth = PMC_USER_CALLCHAIN_PENDING; @@ -4664,7 +4766,7 @@ pmc_add_sample(ring_type_t ring, struct pmc *pm, struct trapframe *tf) ps->ps_nsamples = callchaindepth; /* mark entry as in-use */ if (ring == PMC_UR) { - ps->ps_nsamples_actual = callchaindepth; + ps->ps_nsamples_actual = ps->ps_nsamples; ps->ps_nsamples = PMC_USER_CALLCHAIN_PENDING; } @@ -4690,7 +4792,8 @@ done: * locking primitives supplied by the OS. */ int -pmc_process_interrupt(int ring, struct pmc *pm, struct trapframe *tf) +pmc_process_interrupt_mp(int ring, struct pmc *pm, struct trapframe *tf, + struct pmc_multipart *mp) { struct thread *td; @@ -4698,9 +4801,15 @@ pmc_process_interrupt(int ring, struct pmc *pm, struct trapframe *tf) if ((pm->pm_flags & PMC_F_USERCALLCHAIN) && (td->td_proc->p_flag & P_KPROC) == 0 && !TRAPF_USERMODE(tf)) { atomic_add_int(&td->td_pmcpend, 1); - return (pmc_add_sample(PMC_UR, pm, tf)); + return (pmc_add_sample(PMC_UR, pm, tf, mp)); } - return (pmc_add_sample(ring, pm, tf)); + return (pmc_add_sample(ring, pm, tf, mp)); +} + +int +pmc_process_interrupt(int ring, struct pmc *pm, struct trapframe *tf) +{ + return (pmc_process_interrupt_mp(ring, pm, tf, NULL)); } /* @@ -4763,10 +4872,9 @@ restart: (uintmax_t)counter_u64_fetch(pm->pm_runcount))); if (ring == PMC_UR) { - nsamples = ps->ps_nsamples_actual; counter_u64_add(pmc_stats.pm_merges, 1); - } else - nsamples = 0; + } + nsamples = ps->ps_nsamples_actual; /* * Retrieve the callchain and mark the sample buffer diff --git a/sys/dev/hwpmc/pmc_events.h b/sys/dev/hwpmc/pmc_events.h index ab157cb05dcf..b22ec1919b32 100644 --- a/sys/dev/hwpmc/pmc_events.h +++ b/sys/dev/hwpmc/pmc_events.h @@ -149,6 +149,15 @@ __PMC_EV(K8, NB_HT_BUS2_BANDWIDTH) #define PMC_EV_K8_FIRST PMC_EV_K8_FP_DISPATCHED_FPU_OPS #define PMC_EV_K8_LAST PMC_EV_K8_NB_HT_BUS2_BANDWIDTH +/* AMD IBS PMCs */ + +#define __PMC_EV_IBS() \ +__PMC_EV(IBS, FETCH) \ +__PMC_EV(IBS, OP) + +#define PMC_EV_IBS_FIRST PMC_EV_IBS_FETCH +#define PMC_EV_IBS_LAST PMC_EV_IBS_OP + /* * Events supported by Intel architectural fixed function counters, * from the "Intel 64 and IA-32 Architectures Software Developer's @@ -2398,7 +2407,7 @@ __PMC_EV_ALIAS("unhalted-reference-cycles", IAF_CPU_CLK_UNHALTED_REF) * START #EVENTS DESCRIPTION * 0 0x1000 Reserved * 0x1000 0x0001 TSC - * 0x2000 0x0080 free (was AMD K7 events) + * 0x2000 0x0080 AMD IBS (was AMD K7 events) * 0x2080 0x0100 AMD K8 events * 0x10000 0x0080 INTEL architectural fixed-function events * 0x10080 0x0F80 free (was INTEL architectural programmable events) @@ -2424,6 +2433,8 @@ __PMC_EV_ALIAS("unhalted-reference-cycles", IAF_CPU_CLK_UNHALTED_REF) #define __PMC_EVENTS() \ __PMC_EV_BLOCK(TSC, 0x01000) \ __PMC_EV_TSC() \ + __PMC_EV_BLOCK(IBS, 0x02000) \ + __PMC_EV_IBS() \ __PMC_EV_BLOCK(K8, 0x02080) \ __PMC_EV_K8() \ __PMC_EV_BLOCK(IAF, 0x10000) \ diff --git a/sys/dev/hwt/hwt_vm.c b/sys/dev/hwt/hwt_vm.c index 6c55e218dcec..42fc636e7abc 100644 --- a/sys/dev/hwt/hwt_vm.c +++ b/sys/dev/hwt/hwt_vm.c @@ -109,9 +109,6 @@ hwt_vm_alloc_pages(struct hwt_vm *vm, int kva_req) { vm_paddr_t low, high, boundary; vm_memattr_t memattr; -#ifdef __aarch64__ - uintptr_t va; -#endif int alignment; vm_page_t m; int pflags; @@ -127,7 +124,7 @@ hwt_vm_alloc_pages(struct hwt_vm *vm, int kva_req) if (kva_req) { vm->kvaddr = kva_alloc(vm->npages * PAGE_SIZE); - if (!vm->kvaddr) + if (vm->kvaddr == NULL) return (ENOMEM); } @@ -159,8 +156,7 @@ retry: #endif #ifdef __aarch64__ - va = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)); - cpu_dcache_wb_range((void *)va, PAGE_SIZE); + cpu_dcache_wb_range(VM_PAGE_TO_DMAP(m), PAGE_SIZE); #endif m->valid = VM_PAGE_BITS_ALL; @@ -171,7 +167,7 @@ retry: VM_OBJECT_WLOCK(vm->obj); vm_page_insert(m, vm->obj, i); if (kva_req) - pmap_qenter(vm->kvaddr + i * PAGE_SIZE, &m, 1); + pmap_qenter((char *)vm->kvaddr + i * PAGE_SIZE, &m, 1); VM_OBJECT_WUNLOCK(vm->obj); } @@ -441,7 +437,7 @@ hwt_vm_destroy_buffers(struct hwt_vm *vm) vm_page_t m; int i; - if (vm->ctx->hwt_backend->kva_req && vm->kvaddr != 0) { + if (vm->ctx->hwt_backend->kva_req && vm->kvaddr != NULL) { pmap_qremove(vm->kvaddr, vm->npages); kva_free(vm->kvaddr, vm->npages * PAGE_SIZE); } diff --git a/sys/dev/hwt/hwt_vm.h b/sys/dev/hwt/hwt_vm.h index 5002bd43e093..6c9bdf48ae6d 100644 --- a/sys/dev/hwt/hwt_vm.h +++ b/sys/dev/hwt/hwt_vm.h @@ -33,7 +33,7 @@ struct hwt_vm { vm_page_t *pages; int npages; vm_object_t obj; - vm_offset_t kvaddr; + void *kvaddr; struct cdev *cdev; struct hwt_context *ctx; diff --git a/sys/dev/hyperv/input/hv_kbdc.c b/sys/dev/hyperv/input/hv_kbdc.c index 4f098a99a06b..dc5435b25ff2 100644 --- a/sys/dev/hyperv/input/hv_kbdc.c +++ b/sys/dev/hyperv/input/hv_kbdc.c @@ -515,7 +515,7 @@ static device_method_t kbd_methods[] = { DEVMETHOD(device_probe, hv_kbd_probe), DEVMETHOD(device_attach, hv_kbd_attach), DEVMETHOD(device_detach, hv_kbd_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t kbd_driver = {HVKBD_DRIVER_NAME , kbd_methods, sizeof(hv_kbd_sc)}; diff --git a/sys/dev/hyperv/utilities/hv_kvp.c b/sys/dev/hyperv/utilities/hv_kvp.c index d8ab583d69fa..587e2154f37f 100644 --- a/sys/dev/hyperv/utilities/hv_kvp.c +++ b/sys/dev/hyperv/utilities/hv_kvp.c @@ -905,7 +905,7 @@ static device_method_t kvp_methods[] = { DEVMETHOD(device_probe, hv_kvp_probe), DEVMETHOD(device_attach, hv_kvp_attach), DEVMETHOD(device_detach, hv_kvp_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t kvp_driver = { "hvkvp", kvp_methods, sizeof(hv_kvp_sc)}; diff --git a/sys/dev/hyperv/utilities/hv_snapshot.c b/sys/dev/hyperv/utilities/hv_snapshot.c index 9426544a0700..d8b8df8d8581 100644 --- a/sys/dev/hyperv/utilities/hv_snapshot.c +++ b/sys/dev/hyperv/utilities/hv_snapshot.c @@ -1046,7 +1046,7 @@ static device_method_t vss_methods[] = { DEVMETHOD(device_probe, hv_vss_probe), DEVMETHOD(device_attach, hv_vss_attach), DEVMETHOD(device_detach, hv_vss_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t vss_driver = { "hvvss", vss_methods, sizeof(hv_vss_sc)}; diff --git a/sys/dev/hyperv/vmbus/x86/hyperv_reg.h b/sys/dev/hyperv/vmbus/x86/hyperv_reg.h index 0597a1fea953..e7560d00f25e 100644 --- a/sys/dev/hyperv/vmbus/x86/hyperv_reg.h +++ b/sys/dev/hyperv/vmbus/x86/hyperv_reg.h @@ -45,4 +45,10 @@ #define CPUID_LEAF_HV_IDENTITY 0x40000002 #define CPUID_LEAF_HV_FEATURES 0x40000003 #define CPUID_LEAF_HV_RECOMMENDS 0x40000004 + +#define CPUID_LEAF_HV_STACK_INTERFACE 0x40000081 +#define HYPERV_STACK_INTERFACE_EAX_SIG 0x31235356 /* "VS#1" */ +#define CPUID_LEAF_HV_STACK_PROPERTIES 0x40000082 +#define HYPERV_PROPERTIES_EXT_DEST_ID 0x00000004 + #endif /* !_HYPERV_REG_H_ */ diff --git a/sys/dev/ice/if_ice_iflib.c b/sys/dev/ice/if_ice_iflib.c index 1469d2916465..6ea539d52e02 100644 --- a/sys/dev/ice/if_ice_iflib.c +++ b/sys/dev/ice/if_ice_iflib.c @@ -1907,15 +1907,13 @@ ice_if_promisc_set(if_ctx_t ctx, int flags) ice_set_default_promisc_mask(promisc_mask); - if (multi_enable) - return (EOPNOTSUPP); - if (promisc_enable) { status = ice_set_vsi_promisc(hw, sc->pf_vsi.idx, promisc_mask, 0); if (status && status != ICE_ERR_ALREADY_EXISTS) { device_printf(dev, - "Failed to enable promiscuous mode for PF VSI, err %s aq_err %s\n", + "Failed to enable promiscuous mode for " + "PF VSI, err %s aq_err %s\n", ice_status_str(status), ice_aq_str(hw->adminq.sq_last_status)); return (EIO); @@ -1925,11 +1923,28 @@ ice_if_promisc_set(if_ctx_t ctx, int flags) promisc_mask, 0); if (status) { device_printf(dev, - "Failed to disable promiscuous mode for PF VSI, err %s aq_err %s\n", + "Failed to disable promiscuous mode for" + " PF VSI, err %s aq_err %s\n", ice_status_str(status), ice_aq_str(hw->adminq.sq_last_status)); return (EIO); } + + if (multi_enable) { + ice_clear_bit(ICE_PROMISC_UCAST_TX, promisc_mask); + ice_clear_bit(ICE_PROMISC_UCAST_RX, promisc_mask); + status = ice_set_vsi_promisc(hw, sc->pf_vsi.idx, + promisc_mask, 0); + if (status && status != ICE_ERR_ALREADY_EXISTS) { + device_printf(dev, + "Failed to enable allmulti mode " + "for PF VSI, err %s aq_err %s\n", + ice_status_str(status), + ice_aq_str( + hw->adminq.sq_last_status)); + return (EIO); + } + } } return (0); diff --git a/sys/dev/ichiic/ig4_pci.c b/sys/dev/ichiic/ig4_pci.c index 3a49e220e335..49036c6dabc9 100644 --- a/sys/dev/ichiic/ig4_pci.c +++ b/sys/dev/ichiic/ig4_pci.c @@ -192,6 +192,10 @@ static int ig4iic_pci_detach(device_t dev); #define PCI_CHIP_ARROWLAKE_U_I2C_3 0x777b8086 #define PCI_CHIP_ARROWLAKE_U_I2C_4 0x77508086 #define PCI_CHIP_ARROWLAKE_U_I2C_5 0x77518086 +#define PCI_CHIP_LUNARLAKE_M_I2C_0 0xa8788086 +#define PCI_CHIP_LUNARLAKE_M_I2C_1 0xa8798086 +#define PCI_CHIP_LUNARLAKE_M_I2C_2 0xa87a8086 +#define PCI_CHIP_LUNARLAKE_M_I2C_3 0xa87b8086 struct ig4iic_pci_device { uint32_t devid; @@ -328,6 +332,10 @@ static struct ig4iic_pci_device ig4iic_pci_devices[] = { { PCI_CHIP_ARROWLAKE_U_I2C_3, "Intel Arrow Lake-H/U I2C Controller-3", IG4_TIGERLAKE}, { PCI_CHIP_ARROWLAKE_U_I2C_4, "Intel Arrow Lake-H/U I2C Controller-4", IG4_TIGERLAKE}, { PCI_CHIP_ARROWLAKE_U_I2C_5, "Intel Arrow Lake-H/U I2C Controller-5", IG4_TIGERLAKE}, + { PCI_CHIP_LUNARLAKE_M_I2C_0, "Intel Lunar Lake-M I2C Controller-0", IG4_TIGERLAKE}, + { 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}, }; static int diff --git a/sys/dev/ichsmb/ichsmb_pci.c b/sys/dev/ichsmb/ichsmb_pci.c index 9ffb1de62dac..7d6d94dbb4a4 100644 --- a/sys/dev/ichsmb/ichsmb_pci.c +++ b/sys/dev/ichsmb/ichsmb_pci.c @@ -114,6 +114,7 @@ #define ID_ALDERLAKE 0x7aa3 #define ID_ALDERLAKE2 0x51a3 #define ID_ALDERLAKE3 0x54a3 +#define ID_RAPTORLAKE 0x7a23 #define ID_METEORLAKE 0x7e22 #define ID_METEORLAKE2 0x7f23 #define ID_METEORLAKE3 0xae22 @@ -221,6 +222,8 @@ static const struct pci_device_table ichsmb_devices[] = { PCI_DESCR("Intel Alder Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_ALDERLAKE3), PCI_DESCR("Intel Alder Lake SMBus controller") }, + { PCI_DEV(PCI_VENDOR_INTEL, ID_RAPTORLAKE), + PCI_DESCR("Intel Raptor Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE), PCI_DESCR("Intel Meteor Lake SMBus controller") }, { PCI_DEV(PCI_VENDOR_INTEL, ID_METEORLAKE2), diff --git a/sys/dev/ichwd/i6300esbwd.c b/sys/dev/ichwd/i6300esbwd.c index 03d504a350aa..e810dcd888c4 100644 --- a/sys/dev/ichwd/i6300esbwd.c +++ b/sys/dev/ichwd/i6300esbwd.c @@ -112,7 +112,6 @@ i6300esbwd_event(void *arg, unsigned int cmd, int *error) cmd &= WD_INTERVAL; if (cmd != 0 && (cmd < WD_TO_1MS || (cmd - WD_TO_1MS) >= WDT_PRELOAD_BIT)) { - *error = EINVAL; return; } timeout = 1 << (cmd - WD_TO_1MS); @@ -148,6 +147,8 @@ i6300esbwd_event(void *arg, unsigned int cmd, int *error) regval = i6300esbwd_lock_read(sc); sc->locked = regval & WDT_LOCK; } + /* Set error to 0 to indicate we did something. */ + *error = 0; } static int diff --git a/sys/dev/ida/ida_disk.c b/sys/dev/ida/ida_disk.c index 1e3877652f8a..b884fdf3899e 100644 --- a/sys/dev/ida/ida_disk.c +++ b/sys/dev/ida/ida_disk.c @@ -66,7 +66,7 @@ static device_method_t idad_methods[] = { DEVMETHOD(device_probe, idad_probe), DEVMETHOD(device_attach, idad_attach), DEVMETHOD(device_detach, idad_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t idad_driver = { diff --git a/sys/dev/igc/igc_txrx.c b/sys/dev/igc/igc_txrx.c index 96949492fd24..7ab09078d8f4 100644 --- a/sys/dev/igc/igc_txrx.c +++ b/sys/dev/igc/igc_txrx.c @@ -593,6 +593,6 @@ igc_determine_rsstype(uint16_t pkt_info) case IGC_RXDADV_RSSTYPE_IPV6_TCP_EX: return M_HASHTYPE_RSS_TCP_IPV6_EX; default: - return M_HASHTYPE_OPAQUE; + return M_HASHTYPE_NONE; } } diff --git a/sys/dev/iicbus/adc/ad7417.c b/sys/dev/iicbus/adc/ad7417.c index 33a8f0d55e94..846af9578c5f 100644 --- a/sys/dev/iicbus/adc/ad7417.c +++ b/sys/dev/iicbus/adc/ad7417.c @@ -108,7 +108,7 @@ static device_method_t ad7417_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ad7417_probe), DEVMETHOD(device_attach, ad7417_attach), - { 0, 0 }, + DEVMETHOD_END }; static driver_t ad7417_driver = { diff --git a/sys/dev/iicbus/adc/ads111x.c b/sys/dev/iicbus/adc/ads111x.c index 21924627cc68..8baf9ff789ec 100644 --- a/sys/dev/iicbus/adc/ads111x.c +++ b/sys/dev/iicbus/adc/ads111x.c @@ -407,15 +407,15 @@ ads111x_setup_channel(struct ads111x_softc *sc, int chan, int gainidx, int ratei chantree = SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(devtree), OID_AUTO, chanstr, CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, "channel data"); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chantree), OID_AUTO, - "gain_index", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, + "gain_index", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, sc, chan, ads111x_sysctl_gainidx, "I", "programmable gain amp setting, 0-7"); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chantree), OID_AUTO, - "rate_index", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, + "rate_index", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, sc, chan, ads111x_sysctl_rateidx, "I", "sample rate setting, 0-7"); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(chantree), OID_AUTO, "voltage", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_SKIP | CTLFLAG_NEEDGIANT, sc, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_SKIP | CTLFLAG_MPSAFE, sc, chan, ads111x_sysctl_voltage, "I", "sampled voltage in microvolts"); c->configured = true; @@ -565,13 +565,13 @@ ads111x_attach(device_t dev) ctx = device_get_sysctl_ctx(dev); tree = device_get_sysctl_tree(dev); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "config", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, sc, 0, + "config", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, sc, 0, ads111x_sysctl_config, "I", "configuration register word"); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "lo_thresh", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, sc, 0, + "lo_thresh", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, sc, 0, ads111x_sysctl_lothresh, "I", "comparator low threshold"); SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "hi_thresh", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_NEEDGIANT, sc, 0, + "hi_thresh", CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, sc, 0, ads111x_sysctl_hithresh, "I", "comparator high threshold"); /* Set up channels based on metadata or default config. */ diff --git a/sys/dev/iicbus/controller/twsi/a10_twsi.c b/sys/dev/iicbus/controller/twsi/a10_twsi.c index 4d370674fee3..6caaac99e39d 100644 --- a/sys/dev/iicbus/controller/twsi/a10_twsi.c +++ b/sys/dev/iicbus/controller/twsi/a10_twsi.c @@ -63,6 +63,7 @@ static struct ofw_compat_data compat_data[] = { {"allwinner,sun4i-a10-i2c", 1}, {"allwinner,sun6i-a31-i2c", 1}, {"allwinner,sun8i-a83t-i2c", 1}, + {"allwinner,sun50i-h616-i2c", 1}, {NULL, 0}, }; @@ -138,7 +139,7 @@ static device_method_t a10_twsi_methods[] = { /* OFW methods */ DEVMETHOD(ofw_bus_get_node, a10_twsi_get_node), - { 0, 0 } + DEVMETHOD_END }; DEFINE_CLASS_1(iichb, a10_twsi_driver, a10_twsi_methods, diff --git a/sys/dev/iicbus/controller/twsi/twsi.c b/sys/dev/iicbus/controller/twsi/twsi.c index 46704e1eab65..73412e87d61e 100644 --- a/sys/dev/iicbus/controller/twsi/twsi.c +++ b/sys/dev/iicbus/controller/twsi/twsi.c @@ -869,7 +869,7 @@ static device_method_t twsi_methods[] = { DEVMETHOD(iicbus_read, twsi_read), DEVMETHOD(iicbus_reset, twsi_reset), DEVMETHOD(iicbus_transfer, twsi_transfer), - { 0, 0 } + DEVMETHOD_END }; DEFINE_CLASS_0(twsi, twsi_driver, twsi_methods, diff --git a/sys/dev/iicbus/gpio/tca64xx.c b/sys/dev/iicbus/gpio/tca64xx.c index ab8fedd3f8fd..4920d77dd81c 100644 --- a/sys/dev/iicbus/gpio/tca64xx.c +++ b/sys/dev/iicbus/gpio/tca64xx.c @@ -39,6 +39,7 @@ #include <sys/kernel.h> #include <sys/module.h> #include <sys/proc.h> +#include <sys/sx.h> #include <sys/systm.h> #include <sys/sysctl.h> @@ -93,7 +94,7 @@ struct tca64xx_softc { device_t dev; device_t busdev; enum chip_type chip; - struct mtx mtx; + struct sx mtx; uint32_t addr; uint8_t num_pins; uint8_t in_port_reg; @@ -260,7 +261,7 @@ tca64xx_attach(device_t dev) sc->dev = dev; sc->addr = iicbus_get_addr(dev); - mtx_init(&sc->mtx, "tca64xx gpio", "gpio", MTX_DEF); + sx_init(&sc->mtx, "tca64xx gpio"); OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev); sc->busdev = gpiobus_add_bus(dev); if (sc->busdev == NULL) { @@ -293,7 +294,7 @@ tca64xx_detach(device_t dev) sc = device_get_softc(dev); gpiobus_detach_bus(dev); - mtx_destroy(&sc->mtx); + sx_destroy(&sc->mtx); return (0); } @@ -383,7 +384,7 @@ tca64xx_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) if (pin >= pins) return (EINVAL); - mtx_lock(&sc->mtx); + sx_xlock(&sc->mtx); addr = TCA64XX_REG_ADDR(pin, sc->conf_reg); error = tca64xx_read(dev, addr, &val); @@ -414,7 +415,7 @@ tca64xx_pin_setflags(device_t dev, uint32_t pin, uint32_t flags) error = tca64xx_write(dev, addr, inv_val); fail: - mtx_unlock(&sc->mtx); + sx_unlock(&sc->mtx); return (error); } @@ -478,11 +479,11 @@ tca64xx_pin_set(device_t dev, uint32_t pin, unsigned int val) dbg_dev_printf(dev, "Setting pin: %u to %u\n", pin, val); - mtx_lock(&sc->mtx); + sx_xlock(&sc->mtx); error = tca64xx_read(dev, addr, &value); if (error != 0) { - mtx_unlock(&sc->mtx); + sx_unlock(&sc->mtx); dbg_dev_printf(dev, "Failed to read from register.\n"); return (error); } @@ -494,12 +495,12 @@ tca64xx_pin_set(device_t dev, uint32_t pin, unsigned int val) error = tca64xx_write(dev, addr, value); if (error != 0) { - mtx_unlock(&sc->mtx); + sx_unlock(&sc->mtx); dbg_dev_printf(dev, "Could not write to register.\n"); return (error); } - mtx_unlock(&sc->mtx); + sx_unlock(&sc->mtx); return (0); } @@ -522,11 +523,11 @@ tca64xx_pin_toggle(device_t dev, uint32_t pin) dbg_dev_printf(dev, "Toggling pin: %d\n", pin); - mtx_lock(&sc->mtx); + sx_xlock(&sc->mtx); error = tca64xx_read(dev, addr, &value); if (error != 0) { - mtx_unlock(&sc->mtx); + sx_unlock(&sc->mtx); dbg_dev_printf(dev, "Cannot read from register.\n"); return (error); } @@ -535,12 +536,12 @@ tca64xx_pin_toggle(device_t dev, uint32_t pin) error = tca64xx_write(dev, addr, value); if (error != 0) { - mtx_unlock(&sc->mtx); + sx_unlock(&sc->mtx); dbg_dev_printf(dev, "Cannot write to register.\n"); return (error); } - mtx_unlock(&sc->mtx); + sx_unlock(&sc->mtx); return (0); } diff --git a/sys/dev/iicbus/if_ic.c b/sys/dev/iicbus/if_ic.c index caca35a3d22b..b827cfb32b45 100644 --- a/sys/dev/iicbus/if_ic.c +++ b/sys/dev/iicbus/if_ic.c @@ -111,7 +111,7 @@ static device_method_t ic_methods[] = { /* iicbus interface */ DEVMETHOD(iicbus_intr, icintr), - { 0, 0 } + DEVMETHOD_END }; static driver_t ic_driver = { diff --git a/sys/dev/iicbus/iic.c b/sys/dev/iicbus/iic.c index 3b7d603005aa..c3fcb2dbdaed 100644 --- a/sys/dev/iicbus/iic.c +++ b/sys/dev/iicbus/iic.c @@ -31,11 +31,13 @@ #include <sys/abi_compat.h> #include <sys/bus.h> #include <sys/conf.h> +#include <sys/file.h> #include <sys/fcntl.h> #include <sys/lock.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/module.h> +#include <sys/proc.h> #include <sys/sx.h> #include <sys/systm.h> #include <sys/uio.h> @@ -96,7 +98,10 @@ static void iic_identify(driver_t *driver, device_t parent); static void iicdtor(void *data); static int iicuio_move(struct iic_cdevpriv *priv, struct uio *uio, int last); static int iicuio(struct cdev *dev, struct uio *uio, int ioflag); -static int iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags, bool compat32); +static int iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, + int flags, bool compat32, bool kernel_msgs); +static int iic_linux_rdwr(struct file *fp, struct iic_rdwr_data *d, + int flags, struct thread *td); static device_method_t iic_methods[] = { /* device interface */ @@ -108,7 +113,7 @@ static device_method_t iic_methods[] = { /* iicbus interface */ DEVMETHOD(iicbus_intr, iicbus_generic_intr), - { 0, 0 } + DEVMETHOD_END }; static driver_t iic_driver = { @@ -163,6 +168,7 @@ iic_attach(device_t dev) return (ENXIO); } sc->sc_devnode->si_drv1 = sc; + sc->sc_devnode->si_drv2 = (void *)iic_linux_rdwr; return (0); } @@ -341,7 +347,7 @@ iic_copyinmsgs32(struct iic_rdwr_data *d, struct iic_msg *buf) static int iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags, - bool compat32 __unused) + bool compat32 __unused, bool kernel_msgs) { #ifdef COMPAT_FREEBSD32 struct iic_rdwr_data dswab; @@ -375,7 +381,11 @@ iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags, error = iic_copyinmsgs32(d, buf); else #endif - error = copyin(d->msgs, buf, sizeof(*d->msgs) * d->nmsgs); + if (kernel_msgs) + memcpy(buf, d->msgs, sizeof(*d->msgs) * d->nmsgs); + else + error = copyin(d->msgs, buf, + sizeof(*d->msgs) * d->nmsgs); if (error != 0) { free(buf, M_IIC); return (error); @@ -425,6 +435,27 @@ iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags, } static int +iic_linux_rdwr(struct file *fp, struct iic_rdwr_data *d, int flags, + struct thread *td) +{ + struct file *saved_fp; + struct iic_cdevpriv *priv; + int error; + + saved_fp = td->td_fpop; + td->td_fpop = fp; + error = devfs_get_cdevpriv((void **)&priv); + td->td_fpop = saved_fp; + if (error != 0) + return (error); + + IIC_LOCK(priv); + error = iicrdwr(priv, d, flags, false, true); + IIC_UNLOCK(priv); + return (error); +} + +static int iicioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td) { #ifdef COMPAT_FREEBSD32 @@ -582,7 +613,7 @@ iicioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *t compat32 = false; #endif error = iicrdwr(priv, (struct iic_rdwr_data *)data, flags, - compat32); + compat32, false); break; diff --git a/sys/dev/iicbus/iic.h b/sys/dev/iicbus/iic.h index f6e9360186e0..badfb76e92eb 100644 --- a/sys/dev/iicbus/iic.h +++ b/sys/dev/iicbus/iic.h @@ -31,6 +31,14 @@ #include <sys/ioccom.h> +#ifdef _KERNEL +struct file; +struct iic_rdwr_data; +struct thread; +typedef int iic_linux_rdwr_t(struct file *fp, struct iic_rdwr_data *d, + int flags, struct thread *td); +#endif + /* Designed to be compatible with linux's struct i2c_msg */ struct iic_msg { diff --git a/sys/dev/iicbus/iicbb.c b/sys/dev/iicbus/iicbb.c index 5f6423135f46..a9da39e45122 100644 --- a/sys/dev/iicbus/iicbb.c +++ b/sys/dev/iicbus/iicbb.c @@ -121,7 +121,7 @@ static device_method_t iicbb_methods[] = { DEVMETHOD(ofw_bus_get_node, iicbb_get_node), #endif - { 0, 0 } + DEVMETHOD_END }; driver_t iicbb_driver = { diff --git a/sys/dev/iicbus/iicbus.h b/sys/dev/iicbus/iicbus.h index 74503d3e54ec..a72b004fcc7f 100644 --- a/sys/dev/iicbus/iicbus.h +++ b/sys/dev/iicbus/iicbus.h @@ -57,7 +57,7 @@ struct iicbus_ivar /* Value of 0x100 is reserved for ACPI_IVAR_HANDLE used by acpi_iicbus */ enum { - IICBUS_IVAR_ADDR /* Address or base address */ + IICBUS_IVAR_ADDR = BUS_IVARS_PRIVATE /* Address or base address */ }; #define IICBUS_ACCESSOR(A, B, T) \ diff --git a/sys/dev/iicbus/pwm/adt746x.c b/sys/dev/iicbus/pwm/adt746x.c index 13dcf2b256c0..0e54294cdb42 100644 --- a/sys/dev/iicbus/pwm/adt746x.c +++ b/sys/dev/iicbus/pwm/adt746x.c @@ -131,7 +131,7 @@ static device_method_t adt746x_methods[] = { /* Device interface */ DEVMETHOD(device_probe, adt746x_probe), DEVMETHOD(device_attach, adt746x_attach), - { 0, 0 }, + DEVMETHOD_END }; static driver_t adt746x_driver = { diff --git a/sys/dev/iicbus/rtc/hym8563.c b/sys/dev/iicbus/rtc/hym8563.c index f2db23d47e67..56c5e88edc83 100644 --- a/sys/dev/iicbus/rtc/hym8563.c +++ b/sys/dev/iicbus/rtc/hym8563.c @@ -40,7 +40,8 @@ #include <sys/lock.h> #include <sys/module.h> -#ifdef FDT +#if defined(FDT) && !defined(__powerpc64__) +#include <dev/clk/clk.h> #include <dev/ofw/ofw_bus.h> #include <dev/ofw/ofw_bus_subr.h> #endif @@ -73,14 +74,28 @@ #define HYM8563_WEEKDAY 0x06 #define HYM8563_MONTH 0x07 /* plus 1 bit for century */ #define HYM8563_MONTH_CENTURY (1 << 7) -#define HYM8563_YEAR 0x08 +#define HYM8563_YEAR 0x08 + +#define HYM8563_CLKOUT 0x0D +#define HYM8563_CLKOUT_ENABLE (1 << 7) +#define HYM8563_CLKOUT_32768 0 +#define HYM8563_CLKOUT_1024 1 +#define HYM8563_CLKOUT_32 2 +#define HYM8563_CLKOUT_1 3 +#define HYM8563_CLKOUT_MASK 3 struct hym8563_softc { device_t dev; struct intr_config_hook init_hook; }; -#ifdef FDT +#if defined(FDT) && !defined(__powerpc64__) +/* Clock class and method */ +struct hym8563_clk_sc { + device_t base_dev; +}; + + static struct ofw_compat_data compat_data[] = { {"haoyu,hym8563", 1}, {NULL, 0}, @@ -89,36 +104,201 @@ static struct ofw_compat_data compat_data[] = { static inline int -hym8563_read_buf(struct hym8563_softc *sc, uint8_t reg, uint8_t *buf, - uint16_t buflen) +hym8563_read_buf(device_t dev, uint8_t reg, uint8_t *buf, uint16_t buflen) { - return (iicdev_readfrom(sc->dev, reg, buf, buflen, IIC_WAIT)); + return (iicdev_readfrom(dev, reg, buf, buflen, IIC_WAIT)); } static inline int -hym8563_write_buf(struct hym8563_softc *sc, uint8_t reg, uint8_t *buf, - uint16_t buflen) +hym8563_write_buf(device_t dev, uint8_t reg, uint8_t *buf, uint16_t buflen) { - return (iicdev_writeto(sc->dev, reg, buf, buflen, IIC_WAIT)); + return (iicdev_writeto(dev, reg, buf, buflen, IIC_WAIT)); } static inline int -hym8563_read_1(struct hym8563_softc *sc, uint8_t reg, uint8_t *data) +hym8563_read_1(device_t dev, uint8_t reg, uint8_t *data) { - return (iicdev_readfrom(sc->dev, reg, data, 1, IIC_WAIT)); + return (iicdev_readfrom(dev, reg, data, 1, IIC_WAIT)); } static inline int -hym8563_write_1(struct hym8563_softc *sc, uint8_t reg, uint8_t val) +hym8563_write_1(device_t dev, uint8_t reg, uint8_t val) +{ + + return (iicdev_writeto(dev, reg, &val, 1, IIC_WAIT)); +} + +#if defined(FDT) && !defined(__powerpc64__) +static int +hym8563_clk_set_gate(struct clknode *clk, bool enable) { + struct hym8563_clk_sc *sc; + uint8_t val; + int rv; + + sc = clknode_get_softc(clk); - return (iicdev_writeto(sc->dev, reg, &val, 1, IIC_WAIT)); + rv = hym8563_read_1(sc->base_dev, HYM8563_CLKOUT, &val); + if (rv != 0) { + device_printf(sc->base_dev, + "Cannot read CLKOUT registers: %d\n", rv); + return (rv); + } + if (enable) + val |= HYM8563_CLKOUT_ENABLE; + else + val &= ~HYM8563_CLKOUT_ENABLE; + hym8563_write_1(sc->base_dev, HYM8563_CLKOUT, val); + if (rv != 0) { + device_printf(sc->base_dev, + "Cannot write CLKOUT registers: %d\n", rv); + return (rv); + } + return (0); } static int +hym8563_clk_recalc(struct clknode *clk, uint64_t *freq) +{ + struct hym8563_clk_sc *sc; + uint8_t val; + int rv; + + sc = clknode_get_softc(clk); + + rv = hym8563_read_1(sc->base_dev, HYM8563_CLKOUT, &val); + if (rv != 0) { + device_printf(sc->base_dev, + "Cannot read CLKOUT registers: %d\n", rv); + return (rv); + } + + switch (val & HYM8563_CLKOUT_MASK) { + case HYM8563_CLKOUT_32768: + *freq = 32768; + break; + case HYM8563_CLKOUT_1024: + *freq = 1024; + break; + case HYM8563_CLKOUT_32: + *freq = 32; + break; + case HYM8563_CLKOUT_1: + *freq = 1; + break; + default: + return (EINVAL); + } + return (0); +} +static int +hym8563_clk_set(struct clknode *clk, uint64_t fparent, uint64_t *fout, + int flags, int *stop) +{ + struct hym8563_clk_sc *sc; + uint8_t val, tmp; + int rv; + + sc = clknode_get_softc(clk); + + switch (*fout) { + case 32768: + tmp = HYM8563_CLKOUT_32768; + break; + case 1024: + tmp = HYM8563_CLKOUT_1024; + break; + case 32: + tmp = HYM8563_CLKOUT_32; + break; + case 1: + tmp = HYM8563_CLKOUT_1; + break; + default: + *stop = 1; + return (EINVAL); + } + + rv = hym8563_read_1(sc->base_dev, HYM8563_CLKOUT, &val); + if (rv != 0) { + device_printf(sc->base_dev, + "Cannot read CLKOUT registers: %d\n", rv); + return (rv); + } + + val &= ~HYM8563_CLKOUT_MASK; + val |= tmp; + rv = hym8563_write_1(sc->base_dev, HYM8563_CLKOUT, val); + if (rv != 0) { + device_printf(sc->base_dev, + "Cannot write CLKOUT registers: %d\n", rv); + return (rv); + } + + return (0); +} + +static clknode_method_t hym8563_clk_clknode_methods[] = { + CLKNODEMETHOD(clknode_recalc_freq, hym8563_clk_recalc), + CLKNODEMETHOD(clknode_set_freq, hym8563_clk_set), + CLKNODEMETHOD(clknode_set_gate, hym8563_clk_set_gate), + CLKNODEMETHOD_END +}; + +DEFINE_CLASS_1(hym8563_clk_clknode, hym8563_clk_clknode_class, + hym8563_clk_clknode_methods, sizeof(struct hym8563_clk_sc), + clknode_class); + + +static int +hym8563_attach_clocks(struct hym8563_softc *sc) +{ + struct clkdom *clkdom; + struct clknode_init_def clkidef; + struct clknode *clk; + struct hym8563_clk_sc *clksc; + const char **clknames; + phandle_t node; + int nclks, rv; + + node = ofw_bus_get_node(sc->dev); + + /* clock-output-names are optional. Could use them for clkidef.name. */ + nclks = ofw_bus_string_list_to_array(node, "clock-output-names", + &clknames); + + clkdom = clkdom_create(sc->dev); + + memset(&clkidef, 0, sizeof(clkidef)); + clkidef.id = 1; + clkidef.name = (nclks == 1) ? clknames[0] : "hym8563-clkout"; + clk = clknode_create(clkdom, &hym8563_clk_clknode_class, &clkidef); + if (clk == NULL) { + device_printf(sc->dev, "Cannot create '%s'.\n", clkidef.name); + return (ENXIO); + } + clksc = clknode_get_softc(clk); + clksc->base_dev = sc->dev; + clknode_register(clkdom, clk); + + rv = clkdom_finit(clkdom); + if (rv != 0) { + device_printf(sc->dev, "Cannot finalize clkdom initialization: " + "%d\n", rv); + return (ENXIO); + } + + if (bootverbose) + clkdom_dump(clkdom); + + return (0); +} +#endif + +static int hym8563_gettime(device_t dev, struct timespec *ts) { struct hym8563_softc *sc; @@ -129,7 +309,7 @@ hym8563_gettime(device_t dev, struct timespec *ts) sc = device_get_softc(dev); /* Read all RTC data */ - rv = hym8563_read_buf(sc, HYM8563_SEC, buf, sizeof(buf)); + rv = hym8563_read_buf(sc->dev, HYM8563_SEC, buf, sizeof(buf)); if (rv != 0) { device_printf(sc->dev, "Cannot read time registers: %d\n", rv); return (rv); @@ -154,7 +334,7 @@ hym8563_gettime(device_t dev, struct timespec *ts) if (buf[5] & HYM8563_MONTH_CENTURY) bct.year += 0x100; - clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct); + clock_dbgprint_bcd(sc->dev, CLOCK_DBG_READ, &bct); return (clock_bcd_to_ts(&bct, ts, false)); } @@ -182,14 +362,14 @@ hym8563_settime(device_t dev, struct timespec *ts) buf[5] |= HYM8563_MONTH_CENTURY; /* Stop RTC */ - rv = hym8563_write_1(sc, HYM8563_CTRL1, HYM8563_CTRL1_STOP); + rv = hym8563_write_1(sc->dev, HYM8563_CTRL1, HYM8563_CTRL1_STOP); if (rv != 0) { device_printf(sc->dev, "Cannot write CTRL1 register: %d\n", rv); return (rv); } /* Write all RTC data */ - rv = hym8563_write_buf(sc, HYM8563_SEC, buf, sizeof(buf)); + rv = hym8563_write_buf(sc->dev, HYM8563_SEC, buf, sizeof(buf)); if (rv != 0) { device_printf(sc->dev, "Cannot write time registers: %d\n", rv); return (rv); @@ -197,7 +377,7 @@ hym8563_settime(device_t dev, struct timespec *ts) return (rv); /* Start RTC again */ - rv = hym8563_write_1(sc, HYM8563_CTRL1, 0); + rv = hym8563_write_1(sc->dev, HYM8563_CTRL1, 0); if (rv != 0) { device_printf(sc->dev, "Cannot write CTRL1 register: %d\n", rv); return (rv); @@ -217,14 +397,14 @@ hym8563_init(void *arg) config_intrhook_disestablish(&sc->init_hook); /* Clear CTL1 register (stop and test bits) */ - rv = hym8563_write_1(sc, HYM8563_CTRL1, 0); + rv = hym8563_write_1(sc->dev, HYM8563_CTRL1, 0); if (rv != 0) { device_printf(sc->dev, "Cannot init CTRL1 register: %d\n", rv); return; } - + /* Disable interrupts and alarms */ - rv = hym8563_read_1(sc, HYM8563_CTRL2, ®); + rv = hym8563_read_1(sc->dev, HYM8563_CTRL2, ®); if (rv != 0) { device_printf(sc->dev, "Cannot read CTRL2 register: %d\n", rv); return; @@ -232,7 +412,7 @@ hym8563_init(void *arg) rv &= ~HYM8563_CTRL2_TI_TP; rv &= ~HYM8563_CTRL2_AF; rv &= ~HYM8563_CTRL2_TF; - rv = hym8563_write_1(sc, HYM8563_CTRL2, 0); + rv = hym8563_write_1(sc->dev, HYM8563_CTRL2, 0); if (rv != 0) { device_printf(sc->dev, "Cannot write CTRL2 register: %d\n", rv); return; @@ -250,7 +430,7 @@ static int hym8563_probe(device_t dev) { -#ifdef FDT +#if defined(FDT) && !defined(__powerpc64__) if (!ofw_bus_status_okay(dev)) return (ENXIO); @@ -266,10 +446,15 @@ static int hym8563_attach(device_t dev) { struct hym8563_softc *sc; - + sc = device_get_softc(dev); sc->dev = dev; +#if defined(FDT) && !defined(__powerpc64__) + if (hym8563_attach_clocks(sc) != 0) + return(ENXIO); +#endif + /* * Chip init must wait until interrupts are enabled. Often i2c access * works only when the interrupts are available. @@ -305,7 +490,10 @@ static device_method_t hym8563_methods[] = { static DEFINE_CLASS_0(hym8563_rtc, hym8563_driver, hym8563_methods, sizeof(struct hym8563_softc)); -DRIVER_MODULE(hym8563, iicbus, hym8563_driver, NULL, NULL); +EARLY_DRIVER_MODULE(hym8563, iicbus, hym8563_driver, NULL, NULL, + BUS_PASS_SUPPORTDEV + BUS_PASS_ORDER_FIRST); MODULE_VERSION(hym8563, 1); MODULE_DEPEND(hym8563, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); +#if defined(FDT) && !defined(__powerpc64__) IICBUS_FDT_PNP_INFO(compat_data); +#endif
\ No newline at end of file diff --git a/sys/dev/iicbus/sensor/ds1631.c b/sys/dev/iicbus/sensor/ds1631.c index 519756ae864e..ef71ac6a183c 100644 --- a/sys/dev/iicbus/sensor/ds1631.c +++ b/sys/dev/iicbus/sensor/ds1631.c @@ -101,7 +101,7 @@ static device_method_t ds1631_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ds1631_probe), DEVMETHOD(device_attach, ds1631_attach), - { 0, 0 }, + DEVMETHOD_END }; static driver_t ds1631_driver = { diff --git a/sys/dev/iicbus/sensor/ds1775.c b/sys/dev/iicbus/sensor/ds1775.c index 257879345100..c8d9e5ba1317 100644 --- a/sys/dev/iicbus/sensor/ds1775.c +++ b/sys/dev/iicbus/sensor/ds1775.c @@ -74,7 +74,7 @@ static device_method_t ds1775_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ds1775_probe), DEVMETHOD(device_attach, ds1775_attach), - { 0, 0 }, + DEVMETHOD_END }; static driver_t ds1775_driver = { diff --git a/sys/dev/iicbus/sensor/max6690.c b/sys/dev/iicbus/sensor/max6690.c index 87715229b80c..7640e5e65867 100644 --- a/sys/dev/iicbus/sensor/max6690.c +++ b/sys/dev/iicbus/sensor/max6690.c @@ -87,7 +87,7 @@ static device_method_t max6690_methods[] = { /* Device interface */ DEVMETHOD(device_probe, max6690_probe), DEVMETHOD(device_attach, max6690_attach), - { 0, 0 }, + DEVMETHOD_END }; static driver_t max6690_driver = { diff --git a/sys/dev/iommu/iommu_gas.c b/sys/dev/iommu/iommu_gas.c index 80e37341b3dc..306649db445f 100644 --- a/sys/dev/iommu/iommu_gas.c +++ b/sys/dev/iommu/iommu_gas.c @@ -282,7 +282,7 @@ iommu_gas_fini_domain(struct iommu_domain *domain) entry = RB_MIN(iommu_gas_entries_tree, &domain->rb_root); KASSERT(entry->start == 0, ("start entry start %p", domain)); - KASSERT(entry->end == IOMMU_PAGE_SIZE, ("start entry end %p", domain)); + KASSERT(entry->end == 0, ("start entry end %p", domain)); KASSERT(entry->flags == (IOMMU_MAP_ENTRY_PLACE | IOMMU_MAP_ENTRY_UNMAPPED), ("start entry flags %p", domain)); diff --git a/sys/dev/ipmi/ipmi_acpi.c b/sys/dev/ipmi/ipmi_acpi.c index e51e6364e41e..24c766de4a75 100644 --- a/sys/dev/ipmi/ipmi_acpi.c +++ b/sys/dev/ipmi/ipmi_acpi.c @@ -197,7 +197,7 @@ static device_method_t ipmi_methods[] = { DEVMETHOD(device_probe, ipmi_acpi_probe), DEVMETHOD(device_attach, ipmi_acpi_attach), DEVMETHOD(device_detach, ipmi_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ipmi_acpi_driver = { diff --git a/sys/dev/ipmi/ipmi_isa.c b/sys/dev/ipmi/ipmi_isa.c index 0c74307db00d..6d84496b0ef1 100644 --- a/sys/dev/ipmi/ipmi_isa.c +++ b/sys/dev/ipmi/ipmi_isa.c @@ -277,7 +277,7 @@ static device_method_t ipmi_methods[] = { DEVMETHOD(device_probe, ipmi_isa_probe), DEVMETHOD(device_attach, ipmi_isa_attach), DEVMETHOD(device_detach, ipmi_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ipmi_isa_driver = { diff --git a/sys/dev/ipmi/ipmi_pci.c b/sys/dev/ipmi/ipmi_pci.c index 9067742b3e09..14efb0841590 100644 --- a/sys/dev/ipmi/ipmi_pci.c +++ b/sys/dev/ipmi/ipmi_pci.c @@ -169,7 +169,7 @@ static device_method_t ipmi_methods[] = { DEVMETHOD(device_probe, ipmi_pci_probe), DEVMETHOD(device_attach, ipmi_pci_attach), DEVMETHOD(device_detach, ipmi_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ipmi_pci_driver = { @@ -284,7 +284,7 @@ static device_method_t ipmi2_methods[] = { DEVMETHOD(device_probe, ipmi2_pci_probe), DEVMETHOD(device_attach, ipmi2_pci_attach), DEVMETHOD(device_detach, ipmi_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ipmi2_pci_driver = { diff --git a/sys/dev/ipmi/ipmi_smbus.c b/sys/dev/ipmi/ipmi_smbus.c index 9516b3dfa487..5113a3e5cbad 100644 --- a/sys/dev/ipmi/ipmi_smbus.c +++ b/sys/dev/ipmi/ipmi_smbus.c @@ -118,7 +118,7 @@ static device_method_t ipmi_methods[] = { DEVMETHOD(device_probe, ipmi_smbus_probe), DEVMETHOD(device_attach, ipmi_smbus_attach), DEVMETHOD(device_detach, ipmi_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ipmi_smbus_driver = { diff --git a/sys/dev/ips/ips_disk.c b/sys/dev/ips/ips_disk.c index 09ab571d2734..6a33bff9cbf7 100644 --- a/sys/dev/ips/ips_disk.c +++ b/sys/dev/ips/ips_disk.c @@ -50,7 +50,7 @@ static device_method_t ipsd_methods[] = { DEVMETHOD(device_probe, ipsd_probe), DEVMETHOD(device_attach, ipsd_attach), DEVMETHOD(device_detach, ipsd_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ipsd_driver = { diff --git a/sys/dev/ipw/if_ipw.c b/sys/dev/ipw/if_ipw.c index 9db562669487..a1c4f7ad8041 100644 --- a/sys/dev/ipw/if_ipw.c +++ b/sys/dev/ipw/if_ipw.c @@ -2020,9 +2020,10 @@ ipw_setwepkeys(struct ipw_softc *sc) continue; wepkey.idx = i; - wepkey.len = wk->wk_keylen; + wepkey.len = ieee80211_crypto_get_key_len(wk); memset(wepkey.key, 0, sizeof wepkey.key); - memcpy(wepkey.key, wk->wk_key, wk->wk_keylen); + memcpy(wepkey.key, ieee80211_crypto_get_key_data(wk), + ieee80211_crypto_get_key_len(wk)); DPRINTF(("Setting wep key index %u len %u\n", wepkey.idx, wepkey.len)); error = ipw_cmd(sc, IPW_CMD_SET_WEP_KEY, &wepkey, diff --git a/sys/dev/irdma/fbsd_kcompat.c b/sys/dev/irdma/fbsd_kcompat.c index 32a9bdb4f969..4888c4ddd5ad 100644 --- a/sys/dev/irdma/fbsd_kcompat.c +++ b/sys/dev/irdma/fbsd_kcompat.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2021 - 2023 Intel Corporation + * Copyright (c) 2021 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -36,6 +36,7 @@ #include "ice_rdma.h" #include "irdma_di_if.h" #include "irdma_main.h" +#include "icrdma_hw.h" #include <sys/gsb_crc32.h> #include <netinet/in_fib.h> #include <netinet6/in6_fib.h> @@ -44,6 +45,11 @@ /* additional QP debuging option. Keep false unless needed */ bool irdma_upload_context = false; +u8 irdma_sysctl_max_ord = ICRDMA_MAX_ORD_SIZE; +u8 irdma_sysctl_max_ird = ICRDMA_MAX_IRD_SIZE; +u8 irdma_rdpu_bw_tun = 0; + +static void irdma_modify_rdpu_bw(struct irdma_pci_f *rf); inline u32 irdma_rd32(struct irdma_dev_ctx *dev_ctx, u32 reg){ @@ -566,6 +572,9 @@ irdma_set_rf_user_cfg_params(struct irdma_pci_f *rf) rf->rst_to = IRDMA_RST_TIMEOUT_HZ; /* Enable DCQCN algorithm by default */ rf->dcqcn_ena = true; + + if (irdma_fw_major_ver(&rf->sc_dev) == 2 && irdma_rdpu_bw_tun) + irdma_modify_rdpu_bw(rf); } /** @@ -593,12 +602,87 @@ irdma_sysctl_dcqcn_update(SYSCTL_HANDLER_ARGS) return 0; } +static void +irdma_modify_rdpu_bw(struct irdma_pci_f *rf) +{ + u32 val; +#define GL_RDPU_CNTRL 0x00052054 + + val = rd32(&rf->hw, GL_RDPU_CNTRL); + printf("pf%d Read GL_RDPU_CNTRL[%x] = 0x%08X", + if_getdunit(rf->peer_info->ifp), GL_RDPU_CNTRL, val); + + /* Clear the load balancing bit */ + val &= ~(0x1 << 2); + wr32(&rf->hw, GL_RDPU_CNTRL, val); + val = rd32(&rf->hw, GL_RDPU_CNTRL); + printf("pf%d Set GL_RDPU_CNTRL[%x] = 0x%08X", + if_getdunit(rf->peer_info->ifp), GL_RDPU_CNTRL, val); +} + +enum irdma_qos_info { + IRDMA_QOS_DSCP_MAP = 1, + IRDMA_QOS_DSCP_MODE, + IRDMA_QOS_PRIO_TYPE, + IRDMA_QOS_QS_HANDLE, + IRDMA_QOS_REL_BW, + IRDMA_QOS_TC, + IRDMA_QOS_UP2TC +}; + enum irdma_cqp_stats_info { IRDMA_CQP_REQ_CMDS = 28, IRDMA_CQP_CMPL_CMDS = 29 }; static int +irdma_sysctl_qos(SYSCTL_HANDLER_ARGS) +{ + struct irdma_sc_vsi *vsi = (struct irdma_sc_vsi *)arg1; + char rslt[192] = "no vsi available yet"; + int rslt_size = sizeof(rslt) - 1; + int option = (int)arg2; + int a; + + if (!vsi) { + return sysctl_handle_string(oidp, rslt, sizeof(rslt), req); + + } + + snprintf(rslt, sizeof(rslt), ""); + switch (option) { + case IRDMA_QOS_PRIO_TYPE: + for (a = 0; a < IRDMA_MAX_USER_PRIORITY; a++) + snprintf(rslt, rslt_size, "%s %02x", rslt, vsi->qos[a].prio_type); + break; + case IRDMA_QOS_REL_BW: + for (a = 0; a < IRDMA_MAX_USER_PRIORITY; a++) + snprintf(rslt, rslt_size, "%s %d", rslt, vsi->qos[a].rel_bw); + break; + case IRDMA_QOS_QS_HANDLE: + for (a = 0; a < IRDMA_MAX_USER_PRIORITY; a++) + snprintf(rslt, rslt_size, "%s %d", rslt, vsi->qos[a].qs_handle); + break; + case IRDMA_QOS_TC: + for (a = 0; a < IRDMA_MAX_USER_PRIORITY; a++) + snprintf(rslt, rslt_size, "%s %d", rslt, vsi->qos[a].traffic_class); + break; + case IRDMA_QOS_UP2TC: + for (a = 0; a < IRDMA_MAX_USER_PRIORITY; a++) + snprintf(rslt, rslt_size, "%s %d", rslt, vsi->cfg_check[a].traffic_class); + break; + case IRDMA_QOS_DSCP_MAP: + for (a = 0; a < sizeof(vsi->dscp_map); a++) + snprintf(rslt, rslt_size, "%s%02x", rslt, vsi->dscp_map[a]); + break; + case IRDMA_QOS_DSCP_MODE: + snprintf(rslt, rslt_size, "%d", vsi->dscp_mode); + } + + return sysctl_handle_string(oidp, rslt, sizeof(rslt), req); +} + +static int irdma_sysctl_cqp_stats(SYSCTL_HANDLER_ARGS) { struct irdma_sc_cqp *cqp = (struct irdma_sc_cqp *)arg1; @@ -854,6 +938,7 @@ void irdma_sysctl_settings(struct irdma_pci_f *rf) { struct sysctl_oid_list *irdma_sysctl_oid_list; + u8 ird_ord_limit; irdma_sysctl_oid_list = SYSCTL_CHILDREN(rf->tun_info.irdma_sysctl_tree); @@ -861,6 +946,79 @@ irdma_sysctl_settings(struct irdma_pci_f *rf) OID_AUTO, "upload_context", CTLFLAG_RWTUN, &irdma_upload_context, 0, "allow for generating QP's upload context, default=0"); + + if (rf->protocol_used != IRDMA_IWARP_PROTOCOL_ONLY) + return; + +#define ICRDMA_HW_IRD_ORD_LIMIT 128 + SYSCTL_ADD_U8(&rf->tun_info.irdma_sysctl_ctx, irdma_sysctl_oid_list, + OID_AUTO, "ord_max_value", CTLFLAG_RDTUN, + &irdma_sysctl_max_ord, ICRDMA_MAX_ORD_SIZE, + "Limit Outbound RDMA Read Queue Depth, dflt=32, max=128"); + + SYSCTL_ADD_U8(&rf->tun_info.irdma_sysctl_ctx, irdma_sysctl_oid_list, + OID_AUTO, "ird_max_value", CTLFLAG_RDTUN, + &irdma_sysctl_max_ird, ICRDMA_MAX_IRD_SIZE, + "Limit Inbound RDMA Read Queue Depth, dflt=32, max=128"); + /* + * Ensure the ird/ord is equal and not more than ICRDMA_HW_IRD_ORD_LIMIT + */ + ird_ord_limit = min(irdma_sysctl_max_ord, irdma_sysctl_max_ird); + if (ird_ord_limit > ICRDMA_HW_IRD_ORD_LIMIT) + ird_ord_limit = ICRDMA_HW_IRD_ORD_LIMIT; + irdma_sysctl_max_ird = ird_ord_limit; + irdma_sysctl_max_ord = ird_ord_limit; + + SYSCTL_ADD_U8(&rf->tun_info.irdma_sysctl_ctx, irdma_sysctl_oid_list, + OID_AUTO, "mod_rdpu_bw", CTLFLAG_RDTUN, + &irdma_rdpu_bw_tun, 0, + "Turn off RDPU BW balance, default=0"); +} + +/** + * irdma_qos_info_tunables_init - init tunables to read qos settings + * @rf: RDMA PCI function + */ +void +irdma_qos_info_tunables_init(struct irdma_pci_f *rf) +{ + struct irdma_sc_vsi *vsi = &rf->iwdev->vsi; + struct sysctl_oid_list *qos_oid_list; + + qos_oid_list = SYSCTL_CHILDREN(rf->tun_info.qos_sysctl_tree); + SYSCTL_ADD_U8(&rf->tun_info.irdma_sysctl_ctx, qos_oid_list, + OID_AUTO, "vsi_rel_bw", CTLFLAG_RD, + &vsi->qos_rel_bw, 0, + "qos_rel_bw"); + SYSCTL_ADD_U8(&rf->tun_info.irdma_sysctl_ctx, qos_oid_list, + OID_AUTO, "vsi_prio_type", CTLFLAG_RD, + &vsi->qos_prio_type, 0, "vsi prio type"); + SYSCTL_ADD_PROC(&rf->tun_info.irdma_sysctl_ctx, qos_oid_list, + OID_AUTO, "dscp_mode", CTLFLAG_RD | CTLTYPE_STRING, + vsi, IRDMA_QOS_DSCP_MODE, irdma_sysctl_qos, "A", + "show dscp_mode"); + SYSCTL_ADD_PROC(&rf->tun_info.irdma_sysctl_ctx, qos_oid_list, OID_AUTO, + "dscp_map", CTLFLAG_RD | CTLTYPE_STRING, vsi, + IRDMA_QOS_DSCP_MAP, irdma_sysctl_qos, "A", + "show dscp map"); + SYSCTL_ADD_PROC(&rf->tun_info.irdma_sysctl_ctx, qos_oid_list, OID_AUTO, + "up2tc", CTLFLAG_RD | CTLTYPE_STRING, vsi, + IRDMA_QOS_UP2TC, irdma_sysctl_qos, "A", + "up to tc mapping"); + SYSCTL_ADD_PROC(&rf->tun_info.irdma_sysctl_ctx, qos_oid_list, OID_AUTO, + "qs", CTLFLAG_RD | CTLTYPE_STRING, vsi, + IRDMA_QOS_QS_HANDLE, irdma_sysctl_qos, "A", + "qs_handle"); + SYSCTL_ADD_PROC(&rf->tun_info.irdma_sysctl_ctx, qos_oid_list, OID_AUTO, + "tc", CTLFLAG_RD | CTLTYPE_STRING, vsi, IRDMA_QOS_TC, + irdma_sysctl_qos, "A", "tc list"); + SYSCTL_ADD_PROC(&rf->tun_info.irdma_sysctl_ctx, qos_oid_list, OID_AUTO, + "rel_bw", CTLFLAG_RD | CTLTYPE_STRING, vsi, + IRDMA_QOS_REL_BW, irdma_sysctl_qos, "A", "relative bw"); + SYSCTL_ADD_PROC(&rf->tun_info.irdma_sysctl_ctx, qos_oid_list, OID_AUTO, + "prio_type", CTLFLAG_RD | CTLTYPE_STRING, vsi, + IRDMA_QOS_PRIO_TYPE, irdma_sysctl_qos, "A", + "prio_type"); } void diff --git a/sys/dev/irdma/fbsd_kcompat.h b/sys/dev/irdma/fbsd_kcompat.h index 064963bb93bd..cc51f1e7933a 100644 --- a/sys/dev/irdma/fbsd_kcompat.h +++ b/sys/dev/irdma/fbsd_kcompat.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2021 - 2023 Intel Corporation + * Copyright (c) 2021 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -35,6 +35,7 @@ #ifndef FBSD_KCOMPAT_H #define FBSD_KCOMPAT_H #include "ice_rdma.h" +#include "irdma-abi.h" #define TASKLET_DATA_TYPE unsigned long #define TASKLET_FUNC_TYPE void (*)(TASKLET_DATA_TYPE) @@ -77,9 +78,13 @@ void kc_set_roce_uverbs_cmd_mask(struct irdma_device *iwdev); void kc_set_rdma_uverbs_cmd_mask(struct irdma_device *iwdev); +extern u8 irdma_sysctl_max_ord; +extern u8 irdma_sysctl_max_ird; + struct irdma_tunable_info { struct sysctl_ctx_list irdma_sysctl_ctx; struct sysctl_oid *irdma_sysctl_tree; + struct sysctl_oid *qos_sysctl_tree; struct sysctl_oid *sws_sysctl_tree; char drv_ver[IRDMA_VER_LEN]; u8 roce_ena; @@ -142,7 +147,7 @@ void irdma_destroy_ah(struct ib_ah *ibah, u32 flags); void irdma_destroy_ah_stub(struct ib_ah *ibah, u32 flags); int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata); int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata); -int ib_get_eth_speed(struct ib_device *dev, u32 port_num, u8 *speed, u8 *width); +int ib_get_eth_speed(struct ib_device *dev, u32 port_num, u16 *speed, u8 *width); enum rdma_link_layer irdma_get_link_layer(struct ib_device *ibdev, u8 port_num); int irdma_roce_port_immutable(struct ib_device *ibdev, u8 port_num, @@ -190,6 +195,7 @@ int irdma_addr_resolve_neigh_ipv6(struct irdma_cm_node *cm_node, u32 *dest, int arpindex); void irdma_dcqcn_tunables_init(struct irdma_pci_f *rf); void irdma_sysctl_settings(struct irdma_pci_f *rf); +void irdma_qos_info_tunables_init(struct irdma_pci_f *rf); void irdma_sw_stats_tunables_init(struct irdma_pci_f *rf); u32 irdma_create_stag(struct irdma_device *iwdev); void irdma_free_stag(struct irdma_device *iwdev, u32 stag); @@ -201,6 +207,15 @@ int irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start, u64 len, struct irdma_mr; struct irdma_cq; struct irdma_cq_buf; +int irdma_reg_user_mr_type_qp(struct irdma_mem_reg_req req, + struct ib_udata *udata, + struct irdma_mr *iwmr); +int irdma_reg_user_mr_type_cq(struct irdma_mem_reg_req req, + struct ib_udata *udata, + struct irdma_mr *iwmr); +struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len, + u64 virt, int access, + struct ib_udata *udata); struct ib_mr *irdma_alloc_mr(struct ib_pd *pd, enum ib_mr_type mr_type, u32 max_num_sg, struct ib_udata *udata); int irdma_hwreg_mr(struct irdma_device *iwdev, struct irdma_mr *iwmr, diff --git a/sys/dev/irdma/ice_devids.h b/sys/dev/irdma/ice_devids.h index 57a7f2f7c2af..0cf7aa6aee22 100644 --- a/sys/dev/irdma/ice_devids.h +++ b/sys/dev/irdma/ice_devids.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2019 - 2020 Intel Corporation + * Copyright (c) 2019 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -88,4 +88,28 @@ #define ICE_DEV_ID_E822L_10G_BASE_T 0x1899 /* Intel(R) Ethernet Connection E822-L 1GbE */ #define ICE_DEV_ID_E822L_SGMII 0x189A +/* Intel(R) Ethernet Controller E830-CC for backplane */ +#define ICE_DEV_ID_E830_BACKPLANE 0x12D1 +/* Intel(R) Ethernet Controller E830-CC for QSFP */ +#define ICE_DEV_ID_E830_QSFP56 0x12D2 +/* Intel(R) Ethernet Controller E830-CC for SFP */ +#define ICE_DEV_ID_E830_SFP 0x12D3 +/* Intel(R) Ethernet Controller E830-CC for SFP-DD */ +#define ICE_DEV_ID_E830_SFP_DD 0x12D4 +/* Intel(R) Ethernet Controller E830-C for backplane */ +#define ICE_DEV_ID_E830C_BACKPLANE 0x12D5 +/* Intel(R) Ethernet Controller E830-XXV for backplane */ +#define ICE_DEV_ID_E830_XXV_BACKPLANE 0x12DC +/* Intel(R) Ethernet Controller E830-C for QSFP */ +#define ICE_DEV_ID_E830C_QSFP 0x12D8 +/* Intel(R) Ethernet Controller E830-XXV for QSFP */ +#define ICE_DEV_ID_E830_XXV_QSFP 0x12DD +/* Intel(R) Ethernet Controller E830-C for SFP */ +#define ICE_DEV_ID_E830C_SFP 0x12DA +/* Intel(R) Ethernet Controller E830-XXV for SFP */ +#define ICE_DEV_ID_E830_XXV_SFP 0x12DE +/* Intel(R) Ethernet Controller E835-XXV for SFP */ +#define ICE_DEV_ID_E835_XXV_SFP 0x124A +/* Intel(R) Ethernet Controller E835-CC for QSFP */ +#define ICE_DEV_ID_E835_QSFP 0x1249 #endif /* ICE_DEVIDS_H */ diff --git a/sys/dev/irdma/icrdma.c b/sys/dev/irdma/icrdma.c index a4f3904a820c..aeb07addcff7 100644 --- a/sys/dev/irdma/icrdma.c +++ b/sys/dev/irdma/icrdma.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2021 - 2025 Intel Corporation + * Copyright (c) 2021 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -52,7 +52,7 @@ /** * Driver version */ -char irdma_driver_version[] = "1.2.37-k"; +char irdma_driver_version[] = "1.3.56-k"; /** * irdma_init_tunable - prepare tunables @@ -76,6 +76,10 @@ irdma_init_tunable(struct irdma_pci_f *rf, uint8_t pf_id) irdma_oid_list = SYSCTL_CHILDREN(t_info->irdma_sysctl_tree); + t_info->qos_sysctl_tree = SYSCTL_ADD_NODE(&t_info->irdma_sysctl_ctx, + irdma_oid_list, OID_AUTO, + "qos", CTLFLAG_RD, + NULL, ""); t_info->sws_sysctl_tree = SYSCTL_ADD_NODE(&t_info->irdma_sysctl_ctx, irdma_oid_list, OID_AUTO, "sw_stats", CTLFLAG_RD, @@ -418,6 +422,10 @@ irdma_finalize_task(void *context, int pending) "Starting deferred closing %d (%d)\n", rf->peer_info->pf_id, if_getdunit(peer->ifp)); atomic_dec(&rf->dev_ctx.event_rfcnt); + if (rf->rdma_ver == IRDMA_GEN_2 && !rf->ftype) { + cancel_delayed_work_sync(&iwdev->rf->dwork_cqp_poll); + irdma_free_stag(iwdev->rf->iwdev, iwdev->rf->chk_stag); + } wait_event_timeout(iwdev->suspend_wq, !atomic_read(&rf->dev_ctx.event_rfcnt), IRDMA_MAX_TIMEOUT); @@ -441,7 +449,10 @@ irdma_finalize_task(void *context, int pending) if (iwdev->rf->protocol_used != IRDMA_IWARP_PROTOCOL_ONLY) iwdev->dcb_vlan_mode = l2params.num_tc > 1 && !l2params.dscp_mode; - l2params.mtu = peer->mtu; +#define IRDMA_MIN_MTU_HEADERS IB_GRH_BYTES + IB_BTH_BYTES + 28 + l2params.mtu = (peer->mtu) ? peer->mtu : + ib_mtu_enum_to_int(IB_MTU_256) + + IRDMA_MIN_MTU_HEADERS; status = irdma_rt_init_hw(iwdev, &l2params); if (status) { irdma_pr_err("RT init failed %d\n", status); @@ -454,12 +465,21 @@ irdma_finalize_task(void *context, int pending) irdma_rt_deinit_hw(iwdev); ib_dealloc_device(&iwdev->ibdev); } + irdma_qos_info_tunables_init(rf); irdma_sw_stats_tunables_init(rf); req.type = ICE_RDMA_EVENT_VSI_FILTER_UPDATE; req.enable_filter = true; IRDMA_DI_REQ_HANDLER(peer, &req); irdma_reg_ipaddr_event_cb(rf); atomic_inc(&rf->dev_ctx.event_rfcnt); + if (rf->rdma_ver == IRDMA_GEN_2 && !rf->ftype) { + INIT_DELAYED_WORK(&rf->dwork_cqp_poll, cqp_poll_worker); + rf->chk_stag = irdma_create_stag(rf->iwdev); + rf->used_mrs++; + mod_delayed_work(iwdev->cleanup_wq, &rf->dwork_cqp_poll, + msecs_to_jiffies(5000)); + } + irdma_debug(&rf->sc_dev, IRDMA_DEBUG_INIT, "Deferred opening finished %d (%d)\n", rf->peer_info->pf_id, if_getdunit(peer->ifp)); @@ -562,8 +582,9 @@ irdma_probe(struct ice_rdma_peer *peer) struct irdma_handler *hdl; int err = 0; - irdma_pr_info("probe: irdma-%s peer=%p, peer->pf_id=%d, peer->ifp=%p, peer->ifp->if_dunit=%d, peer->pci_mem->r_bustag=%p\n", - irdma_driver_version, peer, peer->pf_id, peer->ifp, + irdma_pr_info("probe: irdma-%s peer=%p, peer->pf_id=%d, peer->ifp=%p\n", + irdma_driver_version, peer, peer->pf_id, peer->ifp); + irdma_pr_info("peer->ifp->if_dunit=%d, peer->pci_mem->r_bustag=%p\n", if_getdunit(peer->ifp), (void *)(uintptr_t)peer->pci_mem->r_bustag); hdl = irdma_find_handler(peer); @@ -664,6 +685,7 @@ irdma_remove(struct ice_rdma_peer *peer) sysctl_ctx_free(&iwdev->rf->tun_info.irdma_sysctl_ctx); hdl->iwdev->rf->tun_info.irdma_sysctl_tree = NULL; + hdl->iwdev->rf->tun_info.qos_sysctl_tree = NULL; hdl->iwdev->rf->tun_info.sws_sysctl_tree = NULL; irdma_ctrl_deinit_hw(iwdev->rf); diff --git a/sys/dev/irdma/icrdma_hw.c b/sys/dev/irdma/icrdma_hw.c index a046bf18a616..b3ac9ea0f3de 100644 --- a/sys/dev/irdma/icrdma_hw.c +++ b/sys/dev/irdma/icrdma_hw.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2017 - 2023 Intel Corporation + * Copyright (c) 2017 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -35,6 +35,7 @@ #include "osdep.h" #include "irdma_type.h" #include "icrdma_hw.h" +#include "irdma_main.h" void disable_prefetch(struct irdma_hw *hw); @@ -244,11 +245,12 @@ icrdma_init_hw(struct irdma_sc_dev *dev) } void -irdma_init_config_check(struct irdma_config_check *cc, u8 traffic_class, u16 qs_handle) +irdma_init_config_check(struct irdma_config_check *cc, u8 traffic_class, u8 prio, u16 qs_handle) { cc->config_ok = false; cc->traffic_class = traffic_class; cc->qs_handle = qs_handle; + cc->prio = prio; cc->lfc_set = 0; cc->pfc_set = 0; } @@ -256,16 +258,27 @@ irdma_init_config_check(struct irdma_config_check *cc, u8 traffic_class, u16 qs_ static bool irdma_is_lfc_set(struct irdma_config_check *cc, struct irdma_sc_vsi *vsi) { + u32 temp; u32 lfc = 1; + u32 rx_pause_enable, tx_pause_enable; u8 fn_id = vsi->dev->hmc_fn_id; - lfc &= (rd32(vsi->dev->hw, - PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_0 + 4 * fn_id) >> 8); - lfc &= (rd32(vsi->dev->hw, - PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_0 + 4 * fn_id) >> 8); + if (irdma_fw_major_ver(vsi->dev) == 1) { + rx_pause_enable = PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_0; + tx_pause_enable = PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_0; + } else { + rx_pause_enable = CNV_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_0; + tx_pause_enable = CNV_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_0; + } + +#define LFC_ENABLE BIT_ULL(8) +#define LFC_ENABLE_S 8 + temp = rd32(vsi->dev->hw, rx_pause_enable + 4 * fn_id); + lfc &= FIELD_GET(LFC_ENABLE, temp); + temp = rd32(vsi->dev->hw, tx_pause_enable + 4 * fn_id); + lfc &= FIELD_GET(LFC_ENABLE, temp); lfc &= rd32(vsi->dev->hw, PRTMAC_HSEC_CTL_RX_ENABLE_GPP_0 + 4 * vsi->dev->hmc_fn_id); - if (lfc) return true; return false; @@ -290,14 +303,21 @@ static bool irdma_is_pfc_set(struct irdma_config_check *cc, struct irdma_sc_vsi *vsi) { u32 pause; + u32 rx_pause_enable, tx_pause_enable; u8 fn_id = vsi->dev->hmc_fn_id; - pause = (rd32(vsi->dev->hw, - PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_0 + 4 * fn_id) >> - cc->traffic_class) & BIT(0); - pause &= (rd32(vsi->dev->hw, - PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_0 + 4 * fn_id) >> - cc->traffic_class) & BIT(0); + if (irdma_fw_major_ver(vsi->dev) == 1) { + rx_pause_enable = PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_0; + tx_pause_enable = PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_0; + } else { + rx_pause_enable = CNV_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_0; + tx_pause_enable = CNV_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_0; + } + + pause = (rd32(vsi->dev->hw, rx_pause_enable + 4 * fn_id) >> + cc->prio) & BIT(0); + pause &= (rd32(vsi->dev->hw, tx_pause_enable + 4 * fn_id) >> + cc->prio) & BIT(0); return irdma_check_tc_has_pfc(vsi, GLDCB_TC2PFC, cc->traffic_class) && pause; @@ -314,17 +334,18 @@ irdma_is_config_ok(struct irdma_config_check *cc, struct irdma_sc_vsi *vsi) return cc->config_ok; } -#define IRDMA_RCV_WND_NO_FC 65536 -#define IRDMA_RCV_WND_FC 65536 +#define IRDMA_RCV_WND_NO_FC 0x1FFFC +#define IRDMA_RCV_WND_FC 0x3FFFC -#define IRDMA_CWND_NO_FC 0x1 -#define IRDMA_CWND_FC 0x18 +#define IRDMA_CWND_NO_FC 0x20 +#define IRDMA_CWND_FC 0x400 +#define IRDMA_CWND_DCQCN_FC 0x80000 #define IRDMA_RTOMIN_NO_FC 0x5 #define IRDMA_RTOMIN_FC 0x32 #define IRDMA_ACKCREDS_NO_FC 0x02 -#define IRDMA_ACKCREDS_FC 0x06 +#define IRDMA_ACKCREDS_FC 0x1E static void irdma_check_flow_ctrl(struct irdma_sc_vsi *vsi, u8 user_prio, u8 traffic_class) @@ -372,7 +393,7 @@ irdma_check_fc_for_qp(struct irdma_sc_vsi *vsi, struct irdma_sc_qp *sc_qp) struct irdma_config_check *cfg_chk = &vsi->cfg_check[i]; irdma_init_config_check(cfg_chk, - vsi->qos[i].traffic_class, + vsi->qos[i].traffic_class, i, vsi->qos[i].qs_handle); if (sc_qp->qs_handle == cfg_chk->qs_handle) irdma_check_flow_ctrl(vsi, i, cfg_chk->traffic_class); diff --git a/sys/dev/irdma/icrdma_hw.h b/sys/dev/irdma/icrdma_hw.h index b413b478538a..0b48c69ba4ee 100644 --- a/sys/dev/irdma/icrdma_hw.h +++ b/sys/dev/irdma/icrdma_hw.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2017 - 2023 Intel Corporation + * Copyright (c) 2017 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -83,6 +83,16 @@ #define PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_2 0x001e31a8 #define PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_3 0x001e31aC +#define CNV_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_0 0x001e2180 +#define CNV_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_1 0x001e2184 +#define CNV_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_2 0x001e2188 +#define CNV_PRTMAC_HSEC_CTL_RX_PAUSE_ENABLE_3 0x001e218c + +#define CNV_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_0 0x001e21a0 +#define CNV_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_1 0x001e21a4 +#define CNV_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_2 0x001e21a8 +#define CVN_PRTMAC_HSEC_CTL_TX_PAUSE_ENABLE_3 0x001e21ac + #define PRTMAC_HSEC_CTL_RX_ENABLE_GPP_0 0x001e34c0 #define PRTMAC_HSEC_CTL_RX_ENABLE_GPP_1 0x001e34c4 #define PRTMAC_HSEC_CTL_RX_ENABLE_GPP_2 0x001e34c8 @@ -120,8 +130,8 @@ enum icrdma_device_caps_const { ICRDMA_MAX_SGE_RD = 13, ICRDMA_MAX_STATS_COUNT = 128, - ICRDMA_MAX_IRD_SIZE = 32, - ICRDMA_MAX_ORD_SIZE = 32, + ICRDMA_MAX_IRD_SIZE = 8, + ICRDMA_MAX_ORD_SIZE = 8, ICRDMA_MIN_WQ_SIZE = 8 /* WQEs */, ICRDMA_MAX_PUSH_PAGE_COUNT = 256, @@ -130,6 +140,7 @@ enum icrdma_device_caps_const { void icrdma_init_hw(struct irdma_sc_dev *dev); void irdma_init_config_check(struct irdma_config_check *cc, u8 traffic_class, + u8 prio, u16 qs_handle); bool irdma_is_config_ok(struct irdma_config_check *cc, struct irdma_sc_vsi *vsi); void irdma_check_fc_for_tc_update(struct irdma_sc_vsi *vsi, diff --git a/sys/dev/irdma/irdma.h b/sys/dev/irdma/irdma.h index e6e493f1854a..b745626b8b60 100644 --- a/sys/dev/irdma/irdma.h +++ b/sys/dev/irdma/irdma.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2017 - 2022 Intel Corporation + * Copyright (c) 2017 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -99,6 +99,7 @@ #define IRDMA_PFHMC_SDCMD_PMSDPARTSEL BIT(15) #define IRDMA_INVALID_CQ_IDX 0xffffffff +#define IRDMA_Q_INVALID_IDX 0xffff enum irdma_dyn_idx_t { IRDMA_IDX_ITR0 = 0, @@ -195,6 +196,7 @@ struct irdma_uk_attrs { u32 max_hw_wq_quanta; u32 min_hw_cq_size; u32 max_hw_cq_size; + u16 max_hw_push_len; u16 max_hw_sq_chunk; u16 min_hw_wq_size; u8 hw_rev; diff --git a/sys/dev/irdma/irdma_cm.c b/sys/dev/irdma/irdma_cm.c index f3ca761b32f6..669d2cf5cb10 100644 --- a/sys/dev/irdma/irdma_cm.c +++ b/sys/dev/irdma/irdma_cm.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2025 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -38,18 +38,110 @@ static void irdma_cm_post_event(struct irdma_cm_event *event); static void irdma_disconnect_worker(struct work_struct *work); /** - * irdma_free_sqbuf - put back puda buffer if refcount is 0 + * irdma_cm_node_cmp_state - Compare the state of a CM node + * @cm_node: Pointer to the CM node structure + * @state: The state to compare against + * + * This function checks if the current state of the given CM node matches + * the specified state. + * + * Return: true if the states match, false otherwise. + */ +static bool +irdma_cm_node_cmp_state(struct irdma_cm_node *cm_node, + enum irdma_cm_node_state state) +{ + + return cm_node->state == state; +} + +/** + * irdma_cm_node_set_state - Set the state of a CM node + * @cm_node: Pointer to the CM node whose state is to be updated + * @state: The new state to set for the CM node + * + * This function updates the state of the specified CM node to the + * provided state and returns the previous state of the CM node. + * + * Return: The previous state of the CM node. + */ +static enum irdma_cm_node_state +irdma_cm_node_set_state(struct irdma_cm_node *cm_node, + enum irdma_cm_node_state state) +{ + enum irdma_cm_node_state old_state; + + old_state = cm_node->state; + cm_node->state = state; + return old_state; +} + +/** + * irdma_rem_ref_sqbuf - put back puda buffer if refcount is 0 + * @vsi: The VSI structure of the device + * @buf: puda buffer to free + */ +static int +irdma_rem_ref_sqbuf(struct irdma_sc_vsi *vsi, struct irdma_puda_buf *buf) +{ + struct irdma_puda_rsrc *ilq = vsi->ilq; + struct irdma_cm_node *cm_node = buf->scratch; + struct irdma_cm_core *cm_core; + + if (!atomic_dec_and_test(&buf->pb_refcount)) + return 0; + + irdma_puda_ret_bufpool(ilq, buf); + + if (cm_node) { + buf->scratch = NULL; + cm_core = cm_node->cm_core; + cm_core->cm_free_ah(cm_node); + } + + return 1; +} + +/** + * irdma_cm_ilq_cmpl_handler - callback function when ILQ completes a send * @vsi: The VSI structure of the device - * @bufp: puda buffer to free + * @bufp: puda buffer structure from sent packet */ void -irdma_free_sqbuf(struct irdma_sc_vsi *vsi, void *bufp) +irdma_cm_ilq_cmpl_handler(struct irdma_sc_vsi *vsi, void *bufp) { struct irdma_puda_buf *buf = bufp; - struct irdma_puda_rsrc *ilq = vsi->ilq; - if (atomic_dec_and_test(&buf->refcount)) - irdma_puda_ret_bufpool(ilq, buf); + irdma_rem_ref_sqbuf(vsi, buf); +} + +/** + * irdma_cm_send_buf - Sends a buffer using the PUDA ILQ + * @ilq: Pointer to the PUDA (Protocol Unit Data Agent) resource structure + * @buf: Pointer to the PUDA buffer to be sent + * + * This function is responsible for transmitting a buffer through the + * specified PUDA resource. It is typically used in the context of + * managing RDMA connections and their associated data transfers. + * + * Return: 0 on success, or a negative error code on failure. + */ +static int +irdma_cm_send_buf( + struct irdma_puda_rsrc *ilq, + struct irdma_puda_buf *buf +) +{ + int ret; + + if (!atomic_inc_not_zero(&buf->pb_refcount)) + pr_err("irdma: puda buffer refcnt increase from zero\n"); + + ret = irdma_puda_send_buf(ilq, buf); + if (ret) + irdma_rem_ref_sqbuf(ilq->vsi, buf); + + return ret; } /** @@ -255,7 +347,7 @@ irdma_timer_list_prep(struct irdma_cm_core *cm_core, HASH_FOR_EACH_RCU(cm_core->cm_hash_tbl, bkt, cm_node, list) { if ((cm_node->close_entry || cm_node->send_entry) && - atomic_inc_not_zero(&cm_node->refcnt)) + irdma_add_ref_cmnode(cm_node)) list_add(&cm_node->timer_entry, timer_list); } } @@ -304,17 +396,16 @@ irdma_create_event(struct irdma_cm_node *cm_node, static void irdma_free_retrans_entry(struct irdma_cm_node *cm_node) { - struct irdma_device *iwdev = cm_node->iwdev; struct irdma_timer_entry *send_entry; send_entry = cm_node->send_entry; + cm_node->send_entry = NULL; if (!send_entry) return; - cm_node->send_entry = NULL; - irdma_free_sqbuf(&iwdev->vsi, send_entry->sqbuf); + irdma_rem_ref_sqbuf(&cm_node->iwdev->vsi, send_entry->sqbuf); kfree(send_entry); - atomic_dec(&cm_node->refcnt); + irdma_rem_ref_cmnode(cm_node); } /** @@ -367,6 +458,7 @@ irdma_form_ah_cm_frame(struct irdma_cm_node *cm_node, } sqbuf->ah_id = cm_node->ah->ah_info.ah_idx; + sqbuf->ah = cm_node->ah; buf = sqbuf->mem.va; if (options) opts_len = (u32)options->size; @@ -433,7 +525,7 @@ irdma_form_ah_cm_frame(struct irdma_cm_node *cm_node, if (pdata && pdata->addr) memcpy(buf, pdata->addr, pdata->size); - atomic_set(&sqbuf->refcount, 1); + atomic_set(&sqbuf->pb_refcount, 1); irdma_debug_buf(vsi->dev, IRDMA_DEBUG_ILQ, "TRANSMIT ILQ BUFFER", sqbuf->mem.va, sqbuf->totallen); @@ -620,7 +712,7 @@ irdma_form_uda_cm_frame(struct irdma_cm_node *cm_node, if (pdata && pdata->addr) memcpy(buf, pdata->addr, pdata->size); - atomic_set(&sqbuf->refcount, 1); + atomic_set(&sqbuf->pb_refcount, 1); irdma_debug_buf(vsi->dev, IRDMA_DEBUG_ILQ, "TRANSMIT ILQ BUFFER", sqbuf->mem.va, sqbuf->totallen); @@ -667,11 +759,12 @@ irdma_active_open_err(struct irdma_cm_node *cm_node, bool reset) if (reset) { irdma_debug(&cm_node->iwdev->rf->sc_dev, IRDMA_DEBUG_CM, "cm_node=%p state=%d\n", cm_node, cm_node->state); - atomic_inc(&cm_node->refcnt); - irdma_send_reset(cm_node); + irdma_add_ref_cmnode(cm_node); + if (irdma_send_reset(cm_node)) + irdma_rem_ref_cmnode(cm_node); } - cm_node->state = IRDMA_CM_STATE_CLOSED; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); irdma_create_event(cm_node, IRDMA_CM_EVENT_ABORTED); } @@ -685,13 +778,13 @@ irdma_passive_open_err(struct irdma_cm_node *cm_node, bool reset) { irdma_cleanup_retrans_entry(cm_node); cm_node->cm_core->stats_passive_errs++; - cm_node->state = IRDMA_CM_STATE_CLOSED; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); irdma_debug(&cm_node->iwdev->rf->sc_dev, IRDMA_DEBUG_CM, "cm_node=%p state=%d\n", cm_node, cm_node->state); if (reset) irdma_send_reset(cm_node); else - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); } /** @@ -717,7 +810,7 @@ irdma_event_connect_error(struct irdma_cm_event *event) cm_id->provider_data = NULL; irdma_send_cm_event(event->cm_node, cm_id, IW_CM_EVENT_CONNECT_REPLY, -ECONNRESET); - irdma_rem_ref_cm_node(event->cm_node); + irdma_rem_ref_cmnode(event->cm_node); } /** @@ -989,7 +1082,7 @@ irdma_send_mpa_reject(struct irdma_cm_node *cm_node, if (!sqbuf) return -ENOMEM; - cm_node->state = IRDMA_CM_STATE_FIN_WAIT1; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_FIN_WAIT1); return irdma_schedule_cm_timer(cm_node, sqbuf, IRDMA_TIMER_TYPE_SEND, 1, 0); @@ -1028,7 +1121,7 @@ irdma_negotiate_mpa_v2_ird_ord(struct irdma_cm_node *cm_node, goto negotiate_done; } - if (cm_node->state != IRDMA_CM_STATE_MPAREQ_SENT) { + if (!irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_MPAREQ_SENT)) { /* responder */ if (!ord_size && (ctrl_ord & IETF_RDMA0_READ)) cm_node->ird_size = 1; @@ -1108,7 +1201,7 @@ irdma_parse_mpa(struct irdma_cm_node *cm_node, u8 *buf, u32 *type, } cm_node->mpa_frame_rev = mpa_frame->rev; - if (cm_node->state != IRDMA_CM_STATE_MPAREQ_SENT) { + if (!irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_MPAREQ_SENT)) { if (memcmp(mpa_frame->key, IEFT_MPA_KEY_REQ, IETF_MPA_KEY_SIZE)) { irdma_debug(&cm_node->iwdev->rf->sc_dev, IRDMA_DEBUG_CM, @@ -1170,7 +1263,7 @@ irdma_parse_mpa(struct irdma_cm_node *cm_node, u8 *buf, u32 *type, * @close_when_complete: is cm_node to be removed * * note - cm_node needs to be protected before calling this. Encase in: - * irdma_rem_ref_cm_node(cm_core, cm_node); + * irdma_rem_ref_cmnode(cm_core, cm_node); * irdma_schedule_cm_timer(...) * atomic_inc(&cm_node->refcnt); */ @@ -1189,7 +1282,7 @@ irdma_schedule_cm_timer(struct irdma_cm_node *cm_node, new_send = kzalloc(sizeof(*new_send), GFP_ATOMIC); if (!new_send) { if (type != IRDMA_TIMER_TYPE_CLOSE) - irdma_free_sqbuf(vsi, sqbuf); + irdma_rem_ref_sqbuf(vsi, sqbuf); return -ENOMEM; } @@ -1204,6 +1297,7 @@ irdma_schedule_cm_timer(struct irdma_cm_node *cm_node, if (type == IRDMA_TIMER_TYPE_CLOSE) { new_send->timetosend += (HZ / 10); if (cm_node->close_entry) { + irdma_rem_ref_sqbuf(vsi, sqbuf); kfree(new_send); irdma_debug(&cm_node->iwdev->rf->sc_dev, IRDMA_DEBUG_CM, "already close entry\n"); @@ -1213,17 +1307,29 @@ irdma_schedule_cm_timer(struct irdma_cm_node *cm_node, cm_node->close_entry = new_send; } else { /* type == IRDMA_TIMER_TYPE_SEND */ spin_lock_irqsave(&cm_node->retrans_list_lock, flags); + if (cm_node->send_entry) { + spin_unlock_irqrestore(&cm_node->retrans_list_lock, + flags); + irdma_rem_ref_sqbuf(vsi, sqbuf); + kfree(new_send); + + return -EINVAL; + } cm_node->send_entry = new_send; - atomic_inc(&cm_node->refcnt); + irdma_add_ref_cmnode(cm_node); spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); new_send->timetosend = jiffies + IRDMA_RETRY_TIMEOUT; - atomic_inc(&sqbuf->refcount); - irdma_puda_send_buf(vsi->ilq, sqbuf); + if (sqbuf->ah) + atomic_inc(&sqbuf->ah->ah_info.ah_refcnt); + + if (irdma_cm_send_buf(vsi->ilq, new_send->sqbuf)) + cm_core->cm_free_ah(cm_node); + if (!send_retrans) { irdma_cleanup_retrans_entry(cm_node); if (close_when_complete) - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); return 0; } } @@ -1247,21 +1353,22 @@ irdma_schedule_cm_timer(struct irdma_cm_node *cm_node, static void irdma_retrans_expired(struct irdma_cm_node *cm_node) { - enum irdma_cm_node_state state = cm_node->state; + enum irdma_cm_node_state state; - cm_node->state = IRDMA_CM_STATE_CLOSED; + state = irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); switch (state) { case IRDMA_CM_STATE_SYN_RCVD: case IRDMA_CM_STATE_CLOSING: - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); break; case IRDMA_CM_STATE_FIN_WAIT1: case IRDMA_CM_STATE_LAST_ACK: irdma_send_reset(cm_node); break; default: - atomic_inc(&cm_node->refcnt); - irdma_send_reset(cm_node); + irdma_add_ref_cmnode(cm_node); + if (irdma_send_reset(cm_node)) + irdma_rem_ref_cmnode(cm_node); irdma_create_event(cm_node, IRDMA_CM_EVENT_ABORTED); break; } @@ -1297,7 +1404,7 @@ irdma_handle_close_entry(struct irdma_cm_node *cm_node, } } else if (rem_node) { /* TIME_WAIT state */ - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); } kfree(close_entry); @@ -1352,7 +1459,7 @@ irdma_cm_timer_tick(struct timer_list *t) if (!send_entry) goto done; if (time_after(send_entry->timetosend, jiffies)) { - if (cm_node->state != IRDMA_CM_STATE_OFFLOADED) { + if (!irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_OFFLOADED)) { if (nexttimeout > send_entry->timetosend || !settimer) { nexttimeout = send_entry->timetosend; @@ -1364,8 +1471,8 @@ irdma_cm_timer_tick(struct timer_list *t) goto done; } - if (cm_node->state == IRDMA_CM_STATE_OFFLOADED || - cm_node->state == IRDMA_CM_STATE_CLOSED) { + if (irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_OFFLOADED) || + irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_CLOSED)) { irdma_free_retrans_entry(cm_node); goto done; } @@ -1376,7 +1483,7 @@ irdma_cm_timer_tick(struct timer_list *t) spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); irdma_retrans_expired(cm_node); - cm_node->state = IRDMA_CM_STATE_CLOSED; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); spin_lock_irqsave(&cm_node->retrans_list_lock, flags); goto done; } @@ -1384,18 +1491,20 @@ irdma_cm_timer_tick(struct timer_list *t) vsi = &cm_node->iwdev->vsi; if (!cm_node->ack_rcvd) { - atomic_inc(&send_entry->sqbuf->refcount); - irdma_puda_send_buf(vsi->ilq, send_entry->sqbuf); + if (send_entry->sqbuf->ah) + atomic_inc(&send_entry->sqbuf->ah->ah_info.ah_refcnt); + if (irdma_cm_send_buf(vsi->ilq, send_entry->sqbuf)) + cm_core->cm_free_ah(cm_node); + cm_node->cm_core->stats_pkt_retrans++; } spin_lock_irqsave(&cm_node->retrans_list_lock, flags); if (send_entry->send_retrans) { send_entry->retranscount--; - timetosend = (IRDMA_RETRY_TIMEOUT << - (IRDMA_DEFAULT_RETRANS - - send_entry->retranscount)); - + timetosend = IRDMA_RETRY_TIMEOUT << + min(IRDMA_DEFAULT_RETRANS - + send_entry->retranscount, (u32)4); send_entry->timetosend = jiffies + min(timetosend, IRDMA_MAX_TIMEOUT); if (nexttimeout > send_entry->timetosend || !settimer) { @@ -1408,11 +1517,11 @@ irdma_cm_timer_tick(struct timer_list *t) close_when_complete = send_entry->close_when_complete; irdma_free_retrans_entry(cm_node); if (close_when_complete) - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); } done: spin_unlock_irqrestore(&cm_node->retrans_list_lock, flags); - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); } if (settimer) { @@ -1489,8 +1598,15 @@ irdma_send_ack(struct irdma_cm_node *cm_node) sqbuf = cm_node->cm_core->form_cm_frame(cm_node, NULL, NULL, NULL, SET_ACK); - if (sqbuf) - irdma_puda_send_buf(vsi->ilq, sqbuf); + if (sqbuf) { + if (sqbuf->ah) + atomic_inc(&sqbuf->ah->ah_info.ah_refcnt); + + if (irdma_cm_send_buf(vsi->ilq, sqbuf)) + cm_node->cm_core->cm_free_ah(cm_node); + + irdma_rem_ref_sqbuf(vsi, sqbuf); + } } /** @@ -1665,7 +1781,6 @@ u16 irdma_get_vlan_ipv4(struct iw_cm_id *cm_id, u32 *addr) { u16 vlan_id = 0xFFFF; - #ifdef INET if_t netdev; struct vnet *vnet = &init_net; @@ -1831,7 +1946,7 @@ irdma_reset_list_prep(struct irdma_cm_core *cm_core, HASH_FOR_EACH_RCU(cm_core->cm_hash_tbl, bkt, cm_node, list) { if (cm_node->listener == listener && !cm_node->accelerated && - atomic_inc_not_zero(&cm_node->refcnt)) + irdma_add_ref_cmnode(cm_node)) list_add(&cm_node->reset_entry, reset_list); } } @@ -1869,21 +1984,20 @@ irdma_dec_refcnt_listen(struct irdma_cm_core *cm_core, cm_node = container_of(list_pos, struct irdma_cm_node, reset_entry); if (cm_node->state >= IRDMA_CM_STATE_FIN_WAIT1) { - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); continue; } irdma_cleanup_retrans_entry(cm_node); err = irdma_send_reset(cm_node); if (err) { - cm_node->state = IRDMA_CM_STATE_CLOSED; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); irdma_debug(&cm_node->iwdev->rf->sc_dev, IRDMA_DEBUG_CM, "send reset failed\n"); } else { - old_state = cm_node->state; - cm_node->state = IRDMA_CM_STATE_LISTENER_DESTROYED; + old_state = irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_LISTENER_DESTROYED); if (old_state != IRDMA_CM_STATE_MPAREQ_RCVD) - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); } } @@ -1969,7 +2083,7 @@ irdma_find_node(struct irdma_cm_core *cm_core, cm_node->loc_port == loc_port && cm_node->rem_port == rem_port && !memcmp(cm_node->loc_addr, loc_addr, sizeof(cm_node->loc_addr)) && !memcmp(cm_node->rem_addr, rem_addr, sizeof(cm_node->rem_addr))) { - if (!atomic_inc_not_zero(&cm_node->refcnt)) + if (!irdma_add_ref_cmnode(cm_node)) goto exit; rcu_read_unlock(); return cm_node; @@ -2078,10 +2192,24 @@ irdma_cm_create_ah(struct irdma_cm_node *cm_node, bool wait) &cm_node->ah)) return -ENOMEM; + atomic_set(&cm_node->ah->ah_info.ah_refcnt, 1); + return 0; } /** + * irdma_cm_free_ah_worker - async free a cm address handle + * @work: pointer to ah structure + */ +static void +irdma_cm_free_ah_worker(struct work_struct *work) +{ + struct irdma_sc_ah *ah = container_of(work, struct irdma_sc_ah, ah_free_work); + + irdma_puda_free_ah(ah->dev, ah); +} + +/** * irdma_cm_free_ah - free a cm address handle * @cm_node: The connection manager node to create AH for */ @@ -2090,8 +2218,14 @@ irdma_cm_free_ah(struct irdma_cm_node *cm_node) { struct irdma_device *iwdev = cm_node->iwdev; - irdma_puda_free_ah(&iwdev->rf->sc_dev, cm_node->ah); - cm_node->ah = NULL; + if (cm_node->ah) { + if (!atomic_dec_and_test(&cm_node->ah->ah_info.ah_refcnt)) + return; + + INIT_WORK(&cm_node->ah->ah_free_work, irdma_cm_free_ah_worker); + queue_work(iwdev->cleanup_wq, &cm_node->ah->ah_free_work); + cm_node->ah = NULL; + } } /** @@ -2109,11 +2243,12 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev, struct irdma_cm_node *cm_node; int arpindex; if_t netdev = iwdev->netdev; + int ret; /* create an hte and cm_node for this instance */ cm_node = kzalloc(sizeof(*cm_node), GFP_ATOMIC); if (!cm_node) - return NULL; + return ERR_PTR(-ENOMEM); /* set our node specific transport info */ cm_node->ipv4 = cm_info->ipv4; @@ -2170,8 +2305,10 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev, kc_set_loc_seq_num_mss(cm_node); arpindex = irdma_resolve_neigh_lpb_chk(iwdev, cm_node, cm_info); - if (arpindex < 0) + if (arpindex < 0) { + ret = -EINVAL; goto err; + } ether_addr_copy(cm_node->rem_mac, iwdev->rf->arp_table[arpindex].mac_addr); irdma_add_hte_node(cm_core, cm_node); @@ -2181,7 +2318,7 @@ irdma_make_cm_node(struct irdma_cm_core *cm_core, struct irdma_device *iwdev, err: kfree(cm_node); - return NULL; + return ERR_PTR(ret); } static void @@ -2197,6 +2334,9 @@ irdma_destroy_connection(struct irdma_cm_node *cm_node) "node destroyed before established\n"); atomic_dec(&cm_node->listener->pend_accepts_cnt); } + + if (cm_node->send_entry) + irdma_cleanup_retrans_entry(cm_node); if (cm_node->close_entry) irdma_handle_close_entry(cm_node, 0); if (cm_node->listener) { @@ -2237,11 +2377,28 @@ irdma_destroy_connection(struct irdma_cm_node *cm_node) } /** - * irdma_rem_ref_cm_node - destroy an instance of a cm node + * irdma_add_ref_cmnode - add reference to an instance of a cm node + * @cm_node: connection's node + */ +bool +irdma_add_ref_cmnode(struct irdma_cm_node *cm_node) +{ + if (atomic_inc_not_zero(&cm_node->refcnt)) + return true; + + /* + * Trying to add refcount to a cmnode being destroyed. + */ + + return false; +} + +/** + * irdma_rem_ref_cmnode - destroy an instance of a cm node * @cm_node: connection's node */ void -irdma_rem_ref_cm_node(struct irdma_cm_node *cm_node) +irdma_rem_ref_cmnode(struct irdma_cm_node *cm_node) { struct irdma_cm_core *cm_core = cm_node->cm_core; unsigned long flags; @@ -2280,21 +2437,23 @@ irdma_handle_fin_pkt(struct irdma_cm_node *cm_node) case IRDMA_CM_STATE_MPAREJ_RCVD: cm_node->tcp_cntxt.rcv_nxt++; irdma_cleanup_retrans_entry(cm_node); - cm_node->state = IRDMA_CM_STATE_LAST_ACK; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_LAST_ACK); irdma_send_fin(cm_node); break; case IRDMA_CM_STATE_MPAREQ_SENT: irdma_create_event(cm_node, IRDMA_CM_EVENT_ABORTED); cm_node->tcp_cntxt.rcv_nxt++; irdma_cleanup_retrans_entry(cm_node); - cm_node->state = IRDMA_CM_STATE_CLOSED; - atomic_inc(&cm_node->refcnt); - irdma_send_reset(cm_node); + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); + irdma_add_ref_cmnode(cm_node); + if (irdma_send_reset(cm_node)) + irdma_rem_ref_cmnode(cm_node); + break; case IRDMA_CM_STATE_FIN_WAIT1: cm_node->tcp_cntxt.rcv_nxt++; irdma_cleanup_retrans_entry(cm_node); - cm_node->state = IRDMA_CM_STATE_CLOSING; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSING); irdma_send_ack(cm_node); /* * Wait for ACK as this is simultaneous close. After we receive ACK, do not send anything. Just rm the @@ -2304,7 +2463,7 @@ irdma_handle_fin_pkt(struct irdma_cm_node *cm_node) case IRDMA_CM_STATE_FIN_WAIT2: cm_node->tcp_cntxt.rcv_nxt++; irdma_cleanup_retrans_entry(cm_node); - cm_node->state = IRDMA_CM_STATE_TIME_WAIT; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_TIME_WAIT); irdma_send_ack(cm_node); irdma_schedule_cm_timer(cm_node, NULL, IRDMA_TIMER_TYPE_CLOSE, 1, 0); @@ -2312,8 +2471,8 @@ irdma_handle_fin_pkt(struct irdma_cm_node *cm_node) case IRDMA_CM_STATE_TIME_WAIT: cm_node->tcp_cntxt.rcv_nxt++; irdma_cleanup_retrans_entry(cm_node); - cm_node->state = IRDMA_CM_STATE_CLOSED; - irdma_rem_ref_cm_node(cm_node); + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); + irdma_rem_ref_cmnode(cm_node); break; case IRDMA_CM_STATE_OFFLOADED: default: @@ -2347,7 +2506,7 @@ irdma_handle_rst_pkt(struct irdma_cm_node *cm_node, /* Drop down to MPA_V1 */ cm_node->mpa_frame_rev = IETF_MPA_V1; /* send a syn and goto syn sent state */ - cm_node->state = IRDMA_CM_STATE_SYN_SENT; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_SYN_SENT); if (irdma_send_syn(cm_node, 0)) irdma_active_open_err(cm_node, false); break; @@ -2374,8 +2533,8 @@ irdma_handle_rst_pkt(struct irdma_cm_node *cm_node, case IRDMA_CM_STATE_FIN_WAIT1: case IRDMA_CM_STATE_LAST_ACK: case IRDMA_CM_STATE_TIME_WAIT: - cm_node->state = IRDMA_CM_STATE_CLOSED; - irdma_rem_ref_cm_node(cm_node); + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); + irdma_rem_ref_cmnode(cm_node); break; default: break; @@ -2400,7 +2559,7 @@ irdma_handle_rcv_mpa(struct irdma_cm_node *cm_node, err = irdma_parse_mpa(cm_node, dataloc, &res_type, datasize); if (err) { - if (cm_node->state == IRDMA_CM_STATE_MPAREQ_SENT) + if (irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_MPAREQ_SENT)) irdma_active_open_err(cm_node, true); else irdma_passive_open_err(cm_node, true); @@ -2412,7 +2571,7 @@ irdma_handle_rcv_mpa(struct irdma_cm_node *cm_node, if (res_type == IRDMA_MPA_REQUEST_REJECT) irdma_debug(&cm_node->iwdev->rf->sc_dev, IRDMA_DEBUG_CM, "state for reject\n"); - cm_node->state = IRDMA_CM_STATE_MPAREQ_RCVD; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_MPAREQ_RCVD); type = IRDMA_CM_EVENT_MPA_REQ; irdma_send_ack(cm_node); /* ACK received MPA request */ atomic_set(&cm_node->passive_state, @@ -2422,10 +2581,10 @@ irdma_handle_rcv_mpa(struct irdma_cm_node *cm_node, irdma_cleanup_retrans_entry(cm_node); if (res_type == IRDMA_MPA_REQUEST_REJECT) { type = IRDMA_CM_EVENT_MPA_REJECT; - cm_node->state = IRDMA_CM_STATE_MPAREJ_RCVD; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_MPAREJ_RCVD); } else { type = IRDMA_CM_EVENT_CONNECTED; - cm_node->state = IRDMA_CM_STATE_OFFLOADED; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_OFFLOADED); } irdma_send_ack(cm_node); break; @@ -2542,12 +2701,13 @@ irdma_handle_syn_pkt(struct irdma_cm_node *cm_node, cm_node->accept_pend = 1; atomic_inc(&cm_node->listener->pend_accepts_cnt); - cm_node->state = IRDMA_CM_STATE_SYN_RCVD; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_SYN_RCVD); break; case IRDMA_CM_STATE_CLOSED: irdma_cleanup_retrans_entry(cm_node); - atomic_inc(&cm_node->refcnt); - irdma_send_reset(cm_node); + irdma_add_ref_cmnode(cm_node); + if (irdma_send_reset(cm_node)) + irdma_rem_ref_cmnode(cm_node); break; case IRDMA_CM_STATE_OFFLOADED: case IRDMA_CM_STATE_ESTABLISHED: @@ -2605,7 +2765,7 @@ irdma_handle_synack_pkt(struct irdma_cm_node *cm_node, cm_node); break; } - cm_node->state = IRDMA_CM_STATE_MPAREQ_SENT; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_MPAREQ_SENT); break; case IRDMA_CM_STATE_MPAREQ_RCVD: irdma_passive_open_err(cm_node, true); @@ -2613,14 +2773,15 @@ irdma_handle_synack_pkt(struct irdma_cm_node *cm_node, case IRDMA_CM_STATE_LISTENING: cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->th_ack); irdma_cleanup_retrans_entry(cm_node); - cm_node->state = IRDMA_CM_STATE_CLOSED; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); irdma_send_reset(cm_node); break; case IRDMA_CM_STATE_CLOSED: cm_node->tcp_cntxt.loc_seq_num = ntohl(tcph->th_ack); irdma_cleanup_retrans_entry(cm_node); - atomic_inc(&cm_node->refcnt); - irdma_send_reset(cm_node); + irdma_add_ref_cmnode(cm_node); + if (irdma_send_reset(cm_node)) + irdma_rem_ref_cmnode(cm_node); break; case IRDMA_CM_STATE_ESTABLISHED: case IRDMA_CM_STATE_FIN_WAIT1: @@ -2663,7 +2824,7 @@ irdma_handle_ack_pkt(struct irdma_cm_node *cm_node, if (ret) return ret; cm_node->tcp_cntxt.rem_ack_num = ntohl(tcph->th_ack); - cm_node->state = IRDMA_CM_STATE_ESTABLISHED; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_ESTABLISHED); if (datasize) { cm_node->tcp_cntxt.rcv_nxt = inc_sequence + datasize; irdma_handle_rcv_mpa(cm_node, rbuf); @@ -2688,23 +2849,24 @@ irdma_handle_ack_pkt(struct irdma_cm_node *cm_node, break; case IRDMA_CM_STATE_LISTENING: irdma_cleanup_retrans_entry(cm_node); - cm_node->state = IRDMA_CM_STATE_CLOSED; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); irdma_send_reset(cm_node); break; case IRDMA_CM_STATE_CLOSED: irdma_cleanup_retrans_entry(cm_node); - atomic_inc(&cm_node->refcnt); - irdma_send_reset(cm_node); + irdma_add_ref_cmnode(cm_node); + if (irdma_send_reset(cm_node)) + irdma_rem_ref_cmnode(cm_node); break; case IRDMA_CM_STATE_LAST_ACK: case IRDMA_CM_STATE_CLOSING: irdma_cleanup_retrans_entry(cm_node); - cm_node->state = IRDMA_CM_STATE_CLOSED; - irdma_rem_ref_cm_node(cm_node); + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); + irdma_rem_ref_cmnode(cm_node); break; case IRDMA_CM_STATE_FIN_WAIT1: irdma_cleanup_retrans_entry(cm_node); - cm_node->state = IRDMA_CM_STATE_FIN_WAIT2; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_FIN_WAIT2); break; case IRDMA_CM_STATE_SYN_SENT: case IRDMA_CM_STATE_FIN_WAIT2: @@ -2851,8 +3013,8 @@ irdma_create_cm_node(struct irdma_cm_core *cm_core, /* create a CM connection node */ cm_node = irdma_make_cm_node(cm_core, iwdev, cm_info, NULL); - if (!cm_node) - return -ENOMEM; + if (IS_ERR(cm_node)) + return PTR_ERR(cm_node); /* set our node side to client (active) side */ cm_node->tcp_cntxt.client = 1; @@ -2889,13 +3051,13 @@ irdma_cm_reject(struct irdma_cm_node *cm_node, const void *pdata, passive_state = atomic_add_return(1, &cm_node->passive_state); if (passive_state == IRDMA_SEND_RESET_EVENT) { - cm_node->state = IRDMA_CM_STATE_CLOSED; - irdma_rem_ref_cm_node(cm_node); + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); + irdma_rem_ref_cmnode(cm_node); return 0; } - if (cm_node->state == IRDMA_CM_STATE_LISTENER_DESTROYED) { - irdma_rem_ref_cm_node(cm_node); + if (irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_LISTENER_DESTROYED)) { + irdma_rem_ref_cmnode(cm_node); return 0; } @@ -2903,7 +3065,7 @@ irdma_cm_reject(struct irdma_cm_node *cm_node, const void *pdata, if (!ret) return 0; - cm_node->state = IRDMA_CM_STATE_CLOSED; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_CLOSED); if (irdma_send_reset(cm_node)) irdma_debug(&cm_node->iwdev->rf->sc_dev, IRDMA_DEBUG_CM, "send reset failed\n"); @@ -2930,7 +3092,7 @@ irdma_cm_close(struct irdma_cm_node *cm_node) irdma_send_reset(cm_node); break; case IRDMA_CM_STATE_CLOSE_WAIT: - cm_node->state = IRDMA_CM_STATE_LAST_ACK; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_LAST_ACK); irdma_send_fin(cm_node); break; case IRDMA_CM_STATE_FIN_WAIT1: @@ -2948,13 +3110,13 @@ irdma_cm_close(struct irdma_cm_node *cm_node) case IRDMA_CM_STATE_INITED: case IRDMA_CM_STATE_CLOSED: case IRDMA_CM_STATE_LISTENER_DESTROYED: - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); break; case IRDMA_CM_STATE_OFFLOADED: if (cm_node->send_entry) irdma_debug(&cm_node->iwdev->rf->sc_dev, IRDMA_DEBUG_CM, "CM send_entry in OFFLOADED state\n"); - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); break; } @@ -3052,28 +3214,29 @@ irdma_receive_ilq(struct irdma_sc_vsi *vsi, struct irdma_puda_buf *rbuf) cm_info.cm_id = listener->cm_id; cm_node = irdma_make_cm_node(cm_core, iwdev, &cm_info, listener); - if (!cm_node) { + if (IS_ERR(cm_node)) { irdma_debug(&cm_core->iwdev->rf->sc_dev, IRDMA_DEBUG_CM, - "allocate node failed\n"); + "allocate node failed ret=%ld\n", + PTR_ERR(cm_node)); atomic_dec(&listener->refcnt); return; } if (!(tcp_get_flags(tcph) & (TH_RST | TH_FIN))) { - cm_node->state = IRDMA_CM_STATE_LISTENING; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_LISTENING); } else { - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); return; } - atomic_inc(&cm_node->refcnt); - } else if (cm_node->state == IRDMA_CM_STATE_OFFLOADED) { - irdma_rem_ref_cm_node(cm_node); + irdma_add_ref_cmnode(cm_node); + } else if (irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_OFFLOADED)) { + irdma_rem_ref_cmnode(cm_node); return; } irdma_process_pkt(cm_node, rbuf); - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); } static int @@ -3248,7 +3411,7 @@ irdma_cm_init_tsa_conn(struct irdma_qp *iwqp, cm_node->lsmm_size; } - cm_node->state = IRDMA_CM_STATE_OFFLOADED; + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_OFFLOADED); iwqp->tcp_info.tcp_state = IRDMA_TCP_STATE_ESTABLISHED; iwqp->tcp_info.src_mac_addr_idx = iwqp->iwdev->mac_ip_table_idx; @@ -3310,6 +3473,68 @@ irdma_qp_disconnect(struct irdma_qp *iwqp) irdma_cm_close(iwqp->cm_node); } +static void +dump_qp_ae_info(struct irdma_qp *iwqp) +{ + struct irdma_device *iwdev = iwqp->iwdev; + struct irdma_ae_info *ae_info = &iwdev->ae_info; + u16 ae = iwqp->last_aeq; + + if (!ae) + return; + + /* + * When there is a hard link disconnect reduce prints to avoid slowing down qp cleanup. + */ + if (ae == IRDMA_AE_LLP_TOO_MANY_RETRIES) { + unsigned long flags; + u32 retry_cnt; + + spin_lock_irqsave(&ae_info->info_lock, flags); + ae_info->retry_cnt++; + if (time_after(ae_info->retry_delay, jiffies)) { + spin_unlock_irqrestore(&ae_info->info_lock, flags); + return; + } + + retry_cnt = ae_info->retry_cnt; + ae_info->retry_cnt = 0; + ae_info->retry_delay = jiffies + + msecs_to_jiffies(IRDMA_RETRY_PRINT_MS); + spin_unlock_irqrestore(&ae_info->info_lock, flags); + + irdma_dev_err(&iwdev->ibdev, + "qp async event qp_id = %d, ae = 0x%x (%s), qp_cnt = %d\n", + iwqp->sc_qp.qp_uk.qp_id, ae, irdma_get_ae_desc(ae), + retry_cnt); + + return; + } + switch (ae) { + case IRDMA_AE_BAD_CLOSE: + case IRDMA_AE_LLP_CLOSE_COMPLETE: + case IRDMA_AE_LLP_CONNECTION_RESET: + case IRDMA_AE_LLP_FIN_RECEIVED: + case IRDMA_AE_LLP_SYN_RECEIVED: + case IRDMA_AE_LLP_TERMINATE_RECEIVED: + case IRDMA_AE_LLP_DOUBT_REACHABILITY: + case IRDMA_AE_LLP_CONNECTION_ESTABLISHED: + case IRDMA_AE_RESET_SENT: + case IRDMA_AE_TERMINATE_SENT: + case IRDMA_AE_RESET_NOT_SENT: + irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_AEQ, + "qp async avent qp_id = %d, ae = 0x%x (%s), src = %d, ae_cnt = %d\n", + iwqp->sc_qp.qp_uk.qp_id, ae, irdma_get_ae_desc(ae), + iwqp->ae_src, atomic_read(&ae_info->ae_cnt)); + break; + default: + irdma_dev_err(&iwdev->ibdev, + "qp async event qp_id = %d, ae = 0x%x (%s), src = %d, ae_cnt = %d\n", + iwqp->sc_qp.qp_uk.qp_id, ae, irdma_get_ae_desc(ae), + iwqp->ae_src, atomic_read(&ae_info->ae_cnt)); + } +} + /** * irdma_cm_disconn_true - called by worker thread to disconnect qp * @iwqp: associate qp for the connection @@ -3331,11 +3556,15 @@ irdma_cm_disconn_true(struct irdma_qp *iwqp) int err; iwdev = iwqp->iwdev; + + dump_qp_ae_info(iwqp); spin_lock_irqsave(&iwqp->lock, flags); + if (rdma_protocol_roce(&iwdev->ibdev, 1)) { struct ib_qp_attr attr; - if (iwqp->flush_issued || iwqp->sc_qp.qp_uk.destroy_pending) { + if (atomic_read(&iwqp->flush_issued) || + iwqp->sc_qp.qp_uk.destroy_pending) { spin_unlock_irqrestore(&iwqp->lock, flags); return; } @@ -3358,10 +3587,8 @@ irdma_cm_disconn_true(struct irdma_qp *iwqp) issue_close = 1; iwqp->cm_id = NULL; irdma_terminate_del_timer(qp); - if (!iwqp->flush_issued) { - iwqp->flush_issued = 1; + if (!atomic_read(&iwqp->flush_issued)) issue_flush = 1; - } } else if ((original_hw_tcp_state == IRDMA_TCP_STATE_CLOSE_WAIT) || ((original_ibqp_state == IB_QPS_RTS) && (last_ae == IRDMA_AE_LLP_CONNECTION_RESET))) { @@ -3378,10 +3605,8 @@ irdma_cm_disconn_true(struct irdma_qp *iwqp) issue_close = 1; iwqp->cm_id = NULL; qp->term_flags = 0; - if (!iwqp->flush_issued) { - iwqp->flush_issued = 1; + if (!atomic_read(&iwqp->flush_issued)) issue_flush = 1; - } } spin_unlock_irqrestore(&iwqp->lock, flags); @@ -3401,7 +3626,7 @@ irdma_cm_disconn_true(struct irdma_qp *iwqp) spin_unlock_irqrestore(&iwdev->cm_core.ht_lock, flags); return; } - atomic_inc(&iwqp->cm_node->refcnt); + irdma_add_ref_cmnode(iwqp->cm_node); spin_unlock_irqrestore(&iwdev->cm_core.ht_lock, flags); @@ -3424,7 +3649,7 @@ irdma_cm_disconn_true(struct irdma_qp *iwqp) cm_id); irdma_qp_disconnect(iwqp); } - irdma_rem_ref_cm_node(iwqp->cm_node); + irdma_rem_ref_cmnode(iwqp->cm_node); } /** @@ -3544,7 +3769,7 @@ irdma_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) iwpd = iwqp->iwpd; tagged_offset = (uintptr_t)iwqp->ietf_mem.va; ibmr = irdma_reg_phys_mr(&iwpd->ibpd, iwqp->ietf_mem.pa, buf_len, - IB_ACCESS_LOCAL_WRITE, &tagged_offset); + IB_ACCESS_LOCAL_WRITE, &tagged_offset, false); if (IS_ERR(ibmr)) { ret = -ENOMEM; goto error; @@ -3611,7 +3836,7 @@ irdma_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) return 0; error: irdma_free_lsmm_rsrc(iwqp); - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); return ret; } @@ -3761,8 +3986,8 @@ irdma_connect(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) irdma_qp_add_ref(&iwqp->ibqp); cm_id->add_ref(cm_id); - if (cm_node->state != IRDMA_CM_STATE_OFFLOADED) { - cm_node->state = IRDMA_CM_STATE_SYN_SENT; + if (!irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_OFFLOADED)) { + irdma_cm_node_set_state(cm_node, IRDMA_CM_STATE_SYN_SENT); ret = irdma_send_syn(cm_node, 0); if (ret) goto err; @@ -3784,7 +4009,7 @@ err: irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_CM, "connect() FAILED: dest addr=%x:%x:%x:%x", IRDMA_PRINT_IP6(cm_info.rem_addr)); - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); iwdev->cm_core.stats_connect_errs++; return ret; @@ -3955,7 +4180,7 @@ irdma_iw_teardown_list_prep(struct irdma_cm_core *cm_core, if ((disconnect_all || (nfo->vlan_id == cm_node->vlan_id && !memcmp(cm_node->loc_addr, ipaddr, nfo->ipv4 ? 4 : 16))) && - atomic_inc_not_zero(&cm_node->refcnt)) + irdma_add_ref_cmnode(cm_node)) list_add(&cm_node->teardown_entry, teardown_list); } } @@ -4089,7 +4314,7 @@ error: cm_id->provider_data = NULL; irdma_send_cm_event(event->cm_node, cm_id, IW_CM_EVENT_CONNECT_REPLY, status); - irdma_rem_ref_cm_node(event->cm_node); + irdma_rem_ref_cmnode(event->cm_node); } /** @@ -4144,20 +4369,20 @@ irdma_cm_event_handler(struct work_struct *work) break; case IRDMA_CM_EVENT_CONNECTED: if (!event->cm_node->cm_id || - event->cm_node->state != IRDMA_CM_STATE_OFFLOADED) + !irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_OFFLOADED)) break; irdma_cm_event_connected(event); break; case IRDMA_CM_EVENT_MPA_REJECT: if (!event->cm_node->cm_id || - cm_node->state == IRDMA_CM_STATE_OFFLOADED) + irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_OFFLOADED)) break; irdma_send_cm_event(cm_node, cm_node->cm_id, IW_CM_EVENT_CONNECT_REPLY, -ECONNREFUSED); break; case IRDMA_CM_EVENT_ABORTED: if (!event->cm_node->cm_id || - event->cm_node->state == IRDMA_CM_STATE_OFFLOADED) + irdma_cm_node_cmp_state(cm_node, IRDMA_CM_STATE_OFFLOADED)) break; irdma_event_connect_error(event); break; @@ -4167,7 +4392,7 @@ irdma_cm_event_handler(struct work_struct *work) break; } - irdma_rem_ref_cm_node(event->cm_node); + irdma_rem_ref_cmnode(cm_node); kfree(event); } @@ -4178,7 +4403,7 @@ irdma_cm_event_handler(struct work_struct *work) static void irdma_cm_post_event(struct irdma_cm_event *event) { - atomic_inc(&event->cm_node->refcnt); + irdma_add_ref_cmnode(event->cm_node); INIT_WORK(&event->event_work, irdma_cm_event_handler); queue_work(event->cm_node->cm_core->event_wq, &event->event_work); } @@ -4219,7 +4444,7 @@ irdma_cm_teardown_connections(struct irdma_device *iwdev, irdma_modify_qp(&cm_node->iwqp->ibqp, &attr, IB_QP_STATE, NULL); if (iwdev->rf->reset) irdma_cm_disconn(cm_node->iwqp); - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); } if (!rdma_protocol_roce(&iwdev->ibdev, 1)) diff --git a/sys/dev/irdma/irdma_cm.h b/sys/dev/irdma/irdma_cm.h index 36cebdb5bf19..26fbee4499c1 100644 --- a/sys/dev/irdma/irdma_cm.h +++ b/sys/dev/irdma/irdma_cm.h @@ -443,6 +443,7 @@ int irdma_arp_table(struct irdma_pci_f *rf, u32 *ip_addr, bool irdma_port_in_use(struct irdma_cm_core *cm_core, u16 port); void irdma_send_ack(struct irdma_cm_node *cm_node); void irdma_lpb_nop(struct irdma_sc_qp *qp); -void irdma_rem_ref_cm_node(struct irdma_cm_node *cm_node); +bool irdma_add_ref_cmnode(struct irdma_cm_node *cm_node); +void irdma_rem_ref_cmnode(struct irdma_cm_node *cm_node); void irdma_add_conn_est_qh(struct irdma_cm_node *cm_node); #endif /* IRDMA_CM_H */ diff --git a/sys/dev/irdma/irdma_ctrl.c b/sys/dev/irdma/irdma_ctrl.c index 79ed14a60670..c3bddab7f477 100644 --- a/sys/dev/irdma/irdma_ctrl.c +++ b/sys/dev/irdma/irdma_ctrl.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2023 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -81,6 +81,24 @@ irdma_get_qp_from_list(struct list_head *head, } /** + * irdma_get_qp_qs - return qs_handle for the qp + * @qp: qp for qset + * + * Returns the queue set that should be used for a given qp. The qos + * mutex should be acquired before calling. + */ +static u16 irdma_get_qp_qs(struct irdma_sc_qp *qp){ + + struct irdma_sc_vsi *vsi = qp->vsi; + u16 qs_handle; + + qs_handle = + vsi->qos[qp->user_pri].qs_handle; + + return qs_handle; +} + +/** * irdma_sc_suspend_resume_qps - suspend/resume all qp's on VSI * @vsi: the VSI struct pointer * @op: Set to IRDMA_OP_RESUME or IRDMA_OP_SUSPEND @@ -96,18 +114,28 @@ irdma_sc_suspend_resume_qps(struct irdma_sc_vsi *vsi, u8 op) qp = irdma_get_qp_from_list(&vsi->qos[i].qplist, qp); while (qp) { if (op == IRDMA_OP_RESUME) { + if (!qp->suspended) { + qp = irdma_get_qp_from_list(&vsi->qos[i].qplist, + qp); + continue; + } if (!qp->dev->ws_add(vsi, i)) { - qp->qs_handle = - vsi->qos[qp->user_pri].qs_handle; - irdma_cqp_qp_suspend_resume(qp, op); + qp->qs_handle = irdma_get_qp_qs(qp); + if (!irdma_cqp_qp_suspend_resume(qp, op)) + qp->suspended = false; } else { - irdma_cqp_qp_suspend_resume(qp, op); + if (!irdma_cqp_qp_suspend_resume(qp, op)) + qp->suspended = false; irdma_modify_qp_to_err(qp); } } else if (op == IRDMA_OP_SUSPEND) { /* issue cqp suspend command */ - if (!irdma_cqp_qp_suspend_resume(qp, op)) + if ((qp->qp_state == IRDMA_QP_STATE_RTS || + qp->qp_state == IRDMA_QP_STATE_RTR) && + !irdma_cqp_qp_suspend_resume(qp, op)) { atomic_inc(&vsi->qp_suspend_reqs); + qp->suspended = true; + } } qp = irdma_get_qp_from_list(&vsi->qos[i].qplist, qp); } @@ -135,7 +163,7 @@ irdma_set_qos_info(struct irdma_sc_vsi *vsi, struct irdma_l2params *l2p) vsi->qos[i].qs_handle = l2p->qs_handle_list[i]; if (vsi->dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_2) irdma_init_config_check(&vsi->cfg_check[i], - l2p->up2tc[i], + l2p->up2tc[i], i, l2p->qs_handle_list[i]); vsi->qos[i].traffic_class = l2p->up2tc[i]; vsi->qos[i].rel_bw = @@ -197,15 +225,16 @@ irdma_qp_add_qos(struct irdma_sc_qp *qp) { struct irdma_sc_vsi *vsi = qp->vsi; - irdma_debug(qp->dev, IRDMA_DEBUG_DCB, - "DCB: Add qp[%d] UP[%d] qset[%d] on_qoslist[%d]\n", - qp->qp_uk.qp_id, qp->user_pri, qp->qs_handle, - qp->on_qoslist); mutex_lock(&vsi->qos[qp->user_pri].qos_mutex); if (!qp->on_qoslist) { list_add(&qp->list, &vsi->qos[qp->user_pri].qplist); qp->on_qoslist = true; - qp->qs_handle = vsi->qos[qp->user_pri].qs_handle; + qp->qs_handle = irdma_get_qp_qs(qp); + irdma_debug(qp->dev, IRDMA_DEBUG_DCB, + "DCB: Add qp[%d] UP[%d] qset[%d] on_qoslist[%d]\n", + qp->qp_uk.qp_id, qp->user_pri, qp->qs_handle, + qp->on_qoslist); + } mutex_unlock(&vsi->qos[qp->user_pri].qos_mutex); } @@ -362,6 +391,7 @@ irdma_sc_manage_qhash_table_entry(struct irdma_sc_cqp *cqp, u64 qw1 = 0; u64 qw2 = 0; u64 temp; + u16 qs_handle; struct irdma_sc_vsi *vsi = info->vsi; wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); @@ -383,8 +413,10 @@ irdma_sc_manage_qhash_table_entry(struct irdma_sc_cqp *cqp, FIELD_PREP(IRDMA_CQPSQ_QHASH_ADDR2, info->dest_ip[2]) | FIELD_PREP(IRDMA_CQPSQ_QHASH_ADDR3, info->dest_ip[3])); } - qw2 = FIELD_PREP(IRDMA_CQPSQ_QHASH_QS_HANDLE, - vsi->qos[info->user_pri].qs_handle); + + qs_handle = vsi->qos[info->user_pri].qs_handle; + + qw2 = FIELD_PREP(IRDMA_CQPSQ_QHASH_QS_HANDLE, qs_handle); if (info->vlan_valid) qw2 |= FIELD_PREP(IRDMA_CQPSQ_QHASH_VLANID, info->vlan_id); set_64bit_val(wqe, IRDMA_BYTE_16, qw2); @@ -493,7 +525,6 @@ irdma_sc_qp_init(struct irdma_sc_qp *qp, struct irdma_qp_init_info *info) qp->rcv_tph_en = info->rcv_tph_en; qp->xmit_tph_en = info->xmit_tph_en; qp->qp_uk.first_sq_wq = info->qp_uk_init_info.first_sq_wq; - qp->qs_handle = qp->vsi->qos[qp->user_pri].qs_handle; return 0; } @@ -1167,9 +1198,9 @@ irdma_sc_alloc_stag(struct irdma_sc_dev *dev, FIELD_PREP(IRDMA_CQPSQ_STAG_LPBLSIZE, info->chunk_size) | FIELD_PREP(IRDMA_CQPSQ_STAG_HPAGESIZE, page_size) | FIELD_PREP(IRDMA_CQPSQ_STAG_REMACCENABLED, info->remote_access) | - FIELD_PREP(IRDMA_CQPSQ_STAG_USEHMCFNIDX, info->use_hmc_fcn_index) | - FIELD_PREP(IRDMA_CQPSQ_STAG_USEPFRID, info->use_pf_rid) | FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity); + /* for FNIC, a PF can send this WQE for a VF */ + hdr |= FIELD_PREP(IRDMA_CQPSQ_STAG_USEHMCFNIDX, info->use_hmc_fcn_index); irdma_wmb(); /* make sure WQE is written before valid bit is set */ set_64bit_val(wqe, IRDMA_BYTE_24, hdr); @@ -1246,7 +1277,8 @@ irdma_sc_mr_reg_non_shared(struct irdma_sc_dev *dev, set_64bit_val(wqe, IRDMA_BYTE_48, FIELD_PREP(IRDMA_CQPSQ_STAG_FIRSTPMPBLIDX, info->first_pm_pbl_index)); - set_64bit_val(wqe, IRDMA_BYTE_40, info->hmc_fcn_index); + hdr = info->hmc_fcn_index; + set_64bit_val(wqe, IRDMA_BYTE_40, hdr); addr_type = (info->addr_type == IRDMA_ADDR_TYPE_VA_BASED) ? 1 : 0; hdr = FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_REG_MR) | @@ -1257,7 +1289,6 @@ irdma_sc_mr_reg_non_shared(struct irdma_sc_dev *dev, FIELD_PREP(IRDMA_CQPSQ_STAG_REMACCENABLED, remote_access) | FIELD_PREP(IRDMA_CQPSQ_STAG_VABASEDTO, addr_type) | FIELD_PREP(IRDMA_CQPSQ_STAG_USEHMCFNIDX, info->use_hmc_fcn_index) | - FIELD_PREP(IRDMA_CQPSQ_STAG_USEPFRID, info->use_pf_rid) | FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity); irdma_wmb(); /* make sure WQE is written before valid bit is set */ @@ -1299,6 +1330,7 @@ irdma_sc_dealloc_stag(struct irdma_sc_dev *dev, hdr = FIELD_PREP(IRDMA_CQPSQ_OPCODE, IRDMA_CQP_OP_DEALLOC_STAG) | FIELD_PREP(IRDMA_CQPSQ_STAG_MR, info->mr) | + FIELD_PREP(IRDMA_CQPSQ_STAG_SKIPFLUSH, info->skip_flush_markers) | FIELD_PREP(IRDMA_CQPSQ_WQEVALID, cqp->polarity); irdma_wmb(); /* make sure WQE is written before valid bit is set */ @@ -1424,7 +1456,7 @@ irdma_sc_mr_fast_register(struct irdma_sc_qp *qp, set_64bit_val(wqe, IRDMA_BYTE_24, hdr); irdma_debug_buf(qp->dev, IRDMA_DEBUG_WQE, "FAST_REG WQE", wqe, - IRDMA_QP_WQE_MIN_SIZE); + quanta * IRDMA_QP_WQE_MIN_SIZE); if (sq_info.push_wqe) irdma_qp_push_wqe(&qp->qp_uk, wqe, quanta, wqe_idx, post_sq); else if (post_sq) @@ -1970,7 +2002,7 @@ irdma_sc_vsi_init(struct irdma_sc_vsi *vsi, mutex_init(&vsi->qos[i].qos_mutex); INIT_LIST_HEAD(&vsi->qos[i].qplist); } - if (vsi->register_qset) { + if (vsi->dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_2) { vsi->dev->ws_add = irdma_ws_add; vsi->dev->ws_remove = irdma_ws_remove; vsi->dev->ws_reset = irdma_ws_reset; @@ -1982,23 +2014,6 @@ irdma_sc_vsi_init(struct irdma_sc_vsi *vsi, } /** - * irdma_get_stats_idx - Return stats index - * @vsi: pointer to the vsi - */ -static u16 irdma_get_stats_idx(struct irdma_sc_vsi *vsi){ - struct irdma_stats_inst_info stats_info = {0}; - struct irdma_sc_dev *dev = vsi->dev; - - if (dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) { - if (!irdma_cqp_stats_inst_cmd(vsi, IRDMA_OP_STATS_ALLOCATE, - &stats_info)) - return stats_info.stats_idx; - } - - return IRDMA_INVALID_STATS_IDX; -} - -/** * irdma_vsi_stats_init - Initialize the vsi statistics * @vsi: pointer to the vsi structure * @info: The info structure used for initialization @@ -2030,16 +2045,6 @@ irdma_vsi_stats_init(struct irdma_sc_vsi *vsi, /* when stat allocation is not required default to fcn_id. */ vsi->stats_idx = info->fcn_id; - if (info->alloc_stats_inst) { - u16 stats_idx = irdma_get_stats_idx(vsi); - - if (stats_idx != IRDMA_INVALID_STATS_IDX) { - vsi->stats_inst_alloc = true; - vsi->stats_idx = stats_idx; - vsi->pestat->gather_info.use_stats_inst = true; - vsi->pestat->gather_info.stats_inst_index = stats_idx; - } - } return 0; } @@ -2051,16 +2056,6 @@ irdma_vsi_stats_init(struct irdma_sc_vsi *vsi, void irdma_vsi_stats_free(struct irdma_sc_vsi *vsi) { - struct irdma_stats_inst_info stats_info = {0}; - struct irdma_sc_dev *dev = vsi->dev; - - if (dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) { - if (vsi->stats_inst_alloc) { - stats_info.stats_idx = vsi->stats_idx; - irdma_cqp_stats_inst_cmd(vsi, IRDMA_OP_STATS_FREE, - &stats_info); - } - } if (!vsi->pestat) return; @@ -2136,45 +2131,6 @@ irdma_sc_gather_stats(struct irdma_sc_cqp *cqp, } /** - * irdma_sc_manage_stats_inst - allocate or free stats instance - * @cqp: struct for cqp hw - * @info: stats info structure - * @alloc: alloc vs. delete flag - * @scratch: u64 saved to be used during cqp completion - */ -static int -irdma_sc_manage_stats_inst(struct irdma_sc_cqp *cqp, - struct irdma_stats_inst_info *info, - bool alloc, u64 scratch) -{ - __le64 *wqe; - u64 temp; - - wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); - if (!wqe) - return -ENOSPC; - - set_64bit_val(wqe, IRDMA_BYTE_40, - FIELD_PREP(IRDMA_CQPSQ_STATS_HMC_FCN_INDEX, info->hmc_fn_id)); - temp = FIELD_PREP(IRDMA_CQPSQ_STATS_WQEVALID, cqp->polarity) | - FIELD_PREP(IRDMA_CQPSQ_STATS_ALLOC_INST, alloc) | - FIELD_PREP(IRDMA_CQPSQ_STATS_USE_HMC_FCN_INDEX, - info->use_hmc_fcn_index) | - FIELD_PREP(IRDMA_CQPSQ_STATS_INST_INDEX, info->stats_idx) | - FIELD_PREP(IRDMA_CQPSQ_STATS_OP, IRDMA_CQP_OP_MANAGE_STATS); - - irdma_wmb(); /* make sure WQE is written before valid bit is set */ - - set_64bit_val(wqe, IRDMA_BYTE_24, temp); - - irdma_debug_buf(cqp->dev, IRDMA_DEBUG_WQE, "MANAGE_STATS WQE", wqe, - IRDMA_CQP_WQE_SIZE * 8); - - irdma_sc_cqp_post_sq(cqp); - return 0; -} - -/** * irdma_sc_set_up_map - set the up map table * @cqp: struct for cqp hw * @info: User priority map info @@ -2940,7 +2896,7 @@ irdma_sc_parse_fpm_commit_buf(struct irdma_sc_dev *dev, __le64 * buf, IRDMA_HMC_IW_HDR); irdma_sc_decode_fpm_commit(dev, buf, IRDMA_BYTE_152, info, IRDMA_HMC_IW_MD); - if (dev->cqp->protocol_used == IRDMA_IWARP_PROTOCOL_ONLY) { + if (dev->hw_attrs.uk_attrs.hw_rev <= IRDMA_GEN_2) { irdma_sc_decode_fpm_commit(dev, buf, IRDMA_BYTE_160, info, IRDMA_HMC_IW_OOISC); irdma_sc_decode_fpm_commit(dev, buf, IRDMA_BYTE_168, info, @@ -2950,7 +2906,7 @@ irdma_sc_parse_fpm_commit_buf(struct irdma_sc_dev *dev, __le64 * buf, /* searching for the last object in HMC to find the size of the HMC area. */ for (i = IRDMA_HMC_IW_QP; i < IRDMA_HMC_IW_MAX; i++) { - if (info[i].base > max_base) { + if (info[i].base > max_base && info[i].cnt) { max_base = info[i].base; last_hmc_obj = i; } @@ -3079,7 +3035,7 @@ irdma_sc_parse_fpm_query_buf(struct irdma_sc_dev *dev, __le64 * buf, irdma_sc_decode_fpm_query(buf, 144, obj_info, IRDMA_HMC_IW_HDR); irdma_sc_decode_fpm_query(buf, 152, obj_info, IRDMA_HMC_IW_MD); - if (dev->cqp->protocol_used == IRDMA_IWARP_PROTOCOL_ONLY) { + if (dev->hw_attrs.uk_attrs.hw_rev <= IRDMA_GEN_2) { irdma_sc_decode_fpm_query(buf, 160, obj_info, IRDMA_HMC_IW_OOISC); get_64bit_val(buf, IRDMA_BYTE_168, &temp); @@ -3173,8 +3129,8 @@ irdma_sc_cqp_init(struct irdma_sc_cqp *cqp, { u8 hw_sq_size; - if (info->sq_size > IRDMA_CQP_SW_SQSIZE_2048 || - info->sq_size < IRDMA_CQP_SW_SQSIZE_4 || + if (info->sq_size > IRDMA_CQP_SW_SQSIZE_MAX || + info->sq_size < IRDMA_CQP_SW_SQSIZE_MIN || ((info->sq_size & (info->sq_size - 1)))) return -EINVAL; @@ -3202,6 +3158,7 @@ irdma_sc_cqp_init(struct irdma_sc_cqp *cqp, cqp->protocol_used = info->protocol_used; irdma_memcpy(&cqp->dcqcn_params, &info->dcqcn_params, sizeof(cqp->dcqcn_params)); cqp->en_rem_endpoint_trk = info->en_rem_endpoint_trk; + cqp->timer_slots = info->timer_slots; info->dev->cqp = cqp; IRDMA_RING_INIT(cqp->sq_ring, cqp->sq_size); @@ -3262,6 +3219,8 @@ irdma_sc_cqp_create(struct irdma_sc_cqp *cqp, u16 *maj_err, u16 *min_err) temp = FIELD_PREP(IRDMA_CQPHC_ENABLED_VFS, cqp->ena_vf_count) | FIELD_PREP(IRDMA_CQPHC_HMC_PROFILE, cqp->hmc_profile); + if (hw_rev == IRDMA_GEN_2) + temp |= FIELD_PREP(IRDMA_CQPHC_TMR_SLOT, cqp->timer_slots); if (hw_rev >= IRDMA_GEN_2) temp |= FIELD_PREP(IRDMA_CQPHC_EN_REM_ENDPOINT_TRK, cqp->en_rem_endpoint_trk); @@ -3836,10 +3795,9 @@ irdma_sc_cceq_destroy_done(struct irdma_sc_ceq *ceq) /** * irdma_sc_cceq_create - create cceq * @ceq: ceq sc structure - * @scratch: u64 saved to be used during cqp completion */ int -irdma_sc_cceq_create(struct irdma_sc_ceq *ceq, u64 scratch) +irdma_sc_cceq_create(struct irdma_sc_ceq *ceq) { int ret_code; struct irdma_sc_dev *dev = ceq->dev; @@ -3850,7 +3808,7 @@ irdma_sc_cceq_create(struct irdma_sc_ceq *ceq, u64 scratch) if (ret_code) return ret_code; } - ret_code = irdma_sc_ceq_create(ceq, scratch, true); + ret_code = irdma_sc_ceq_create(ceq, 0, true); if (!ret_code) return irdma_sc_cceq_create_done(ceq); @@ -4081,7 +4039,9 @@ irdma_sc_aeq_destroy(struct irdma_sc_aeq *aeq, u64 scratch, bool post_sq) u64 hdr; dev = aeq->dev; - writel(0, dev->hw_regs[IRDMA_PFINT_AEQCTL]); + + if (dev->hw_attrs.uk_attrs.hw_rev <= IRDMA_GEN_2) + writel(0, dev->hw_regs[IRDMA_PFINT_AEQCTL]); cqp = dev->cqp; wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); @@ -4180,6 +4140,7 @@ irdma_sc_get_next_aeqe(struct irdma_sc_aeq *aeq, case IRDMA_AE_LCE_QP_CATASTROPHIC: case IRDMA_AE_LLP_DOUBT_REACHABILITY: case IRDMA_AE_LLP_CONNECTION_ESTABLISHED: + case IRDMA_AE_LLP_TOO_MANY_RNRS: case IRDMA_AE_RESET_SENT: case IRDMA_AE_TERMINATE_SENT: case IRDMA_AE_RESET_NOT_SENT: @@ -4388,8 +4349,10 @@ irdma_sc_ccq_destroy(struct irdma_sc_cq *ccq, u64 scratch, bool post_sq) u64 hdr; int ret_code = 0; u32 tail, val, error; + struct irdma_sc_dev *dev; cqp = ccq->dev->cqp; + dev = ccq->dev; wqe = irdma_sc_cqp_get_next_send_wqe(cqp, scratch); if (!wqe) return -ENOSPC; @@ -4418,10 +4381,11 @@ irdma_sc_ccq_destroy(struct irdma_sc_cq *ccq, u64 scratch, bool post_sq) if (post_sq) { irdma_sc_cqp_post_sq(cqp); ret_code = irdma_cqp_poll_registers(cqp, tail, - cqp->dev->hw_attrs.max_done_count); + dev->hw_attrs.max_done_count); } cqp->process_cqp_sds = irdma_update_sds_noccq; + dev->ccq = NULL; return ret_code; } @@ -4792,8 +4756,11 @@ irdma_sc_query_rdma_features(struct irdma_sc_cqp *cqp, int irdma_get_rdma_features(struct irdma_sc_dev *dev) { - int ret_code, byte_idx, feat_type, feat_cnt, feat_idx; struct irdma_dma_mem feat_buf; + u16 feat_cnt; + u16 feat_idx; + u8 feat_type; + int ret_code; u64 temp; feat_buf.size = IRDMA_FEATURE_BUF_SIZE; @@ -4834,13 +4801,18 @@ irdma_get_rdma_features(struct irdma_sc_dev *dev) } } - irdma_debug_buf(dev, IRDMA_DEBUG_WQE, "QUERY RDMA FEATURES", feat_buf.va, - feat_cnt * 8); + irdma_debug_buf(dev, IRDMA_DEBUG_WQE, "QUERY RDMA FEATURES", + feat_buf.va, feat_cnt * 8); - for (byte_idx = 0, feat_idx = 0; feat_idx < min(feat_cnt, IRDMA_MAX_FEATURES); - feat_idx++, byte_idx += 8) { - get_64bit_val(feat_buf.va, byte_idx, &temp); + for (feat_idx = 0; feat_idx < feat_cnt; feat_idx++) { + get_64bit_val(feat_buf.va, feat_idx * 8, &temp); feat_type = FIELD_GET(IRDMA_FEATURE_TYPE, temp); + + if (feat_type >= IRDMA_MAX_FEATURES) { + irdma_debug(dev, IRDMA_DEBUG_DEV, + "unknown feature type %u\n", feat_type); + continue; + } dev->feature_info[feat_type] = temp; } exit: @@ -4899,6 +4871,28 @@ cfg_fpm_value_gen_2(struct irdma_sc_dev *dev, } /** + * irdma_cfg_sd_mem - allocate sd memory + * @dev: sc device struct + * @hmc_info: ptr to irdma_hmc_obj_info struct + */ +static int +irdma_cfg_sd_mem(struct irdma_sc_dev *dev, + struct irdma_hmc_info *hmc_info) +{ + struct irdma_virt_mem virt_mem; + u32 mem_size; + + mem_size = sizeof(struct irdma_hmc_sd_entry) * hmc_info->sd_table.sd_cnt; + virt_mem.size = mem_size; + virt_mem.va = kzalloc(virt_mem.size, GFP_KERNEL); + if (!virt_mem.va) + return -ENOMEM; + hmc_info->sd_table.sd_entry = virt_mem.va; + + return 0; +} + +/** * irdma_cfg_fpm_val - configure HMC objects * @dev: sc device struct * @qp_count: desired qp count @@ -4906,10 +4900,8 @@ cfg_fpm_value_gen_2(struct irdma_sc_dev *dev, int irdma_cfg_fpm_val(struct irdma_sc_dev *dev, u32 qp_count) { - struct irdma_virt_mem virt_mem; - u32 i, mem_size; u32 qpwanted, mrwanted, pblewanted; - u32 hte; + u32 hte, i; u32 sd_needed; u32 sd_diff; u32 loop_count = 0; @@ -4934,7 +4926,7 @@ irdma_cfg_fpm_val(struct irdma_sc_dev *dev, u32 qp_count) hmc_info->hmc_obj[i].cnt = hmc_info->hmc_obj[i].max_cnt; sd_needed = irdma_est_sd(dev, hmc_info); - irdma_debug(dev, IRDMA_DEBUG_HMC, "sd count %d where max sd is %d\n", + irdma_debug(dev, IRDMA_DEBUG_HMC, "sd count %u where max sd is %u\n", hmc_info->sd_table.sd_cnt, max_sds); qpwanted = min(qp_count, hmc_info->hmc_obj[IRDMA_HMC_IW_QP].max_cnt); @@ -4945,7 +4937,7 @@ irdma_cfg_fpm_val(struct irdma_sc_dev *dev, u32 qp_count) pblewanted = hmc_info->hmc_obj[IRDMA_HMC_IW_PBLE].max_cnt; irdma_debug(dev, IRDMA_DEBUG_HMC, - "req_qp=%d max_sd=%d, max_qp = %d, max_cq=%d, max_mr=%d, max_pble=%d, mc=%d, av=%d\n", + "req_qp=%d max_sd=%u, max_qp = %u, max_cq=%u, max_mr=%u, max_pble=%u, mc=%d, av=%u\n", qp_count, max_sds, hmc_info->hmc_obj[IRDMA_HMC_IW_QP].max_cnt, hmc_info->hmc_obj[IRDMA_HMC_IW_CQ].max_cnt, @@ -4959,8 +4951,7 @@ irdma_cfg_fpm_val(struct irdma_sc_dev *dev, u32 qp_count) hmc_info->hmc_obj[IRDMA_HMC_IW_FSIAV].max_cnt; hmc_info->hmc_obj[IRDMA_HMC_IW_ARP].cnt = hmc_info->hmc_obj[IRDMA_HMC_IW_ARP].max_cnt; - if (dev->hw_attrs.uk_attrs.hw_rev <= IRDMA_GEN_2) - hmc_info->hmc_obj[IRDMA_HMC_IW_APBVT_ENTRY].cnt = 1; + hmc_info->hmc_obj[IRDMA_HMC_IW_APBVT_ENTRY].cnt = 1; while (irdma_q1_cnt(dev, hmc_info, qpwanted) > hmc_info->hmc_obj[IRDMA_HMC_IW_Q1].max_cnt) qpwanted /= 2; @@ -5013,11 +5004,12 @@ irdma_cfg_fpm_val(struct irdma_sc_dev *dev, u32 qp_count) if (!(loop_count % 2) && qpwanted > 128) { qpwanted /= 2; } else { - mrwanted /= 2; pblewanted /= 2; + mrwanted /= 2; } continue; } + if (dev->cqp->hmc_profile != IRDMA_HMC_PROFILE_FAVOR_VF && pblewanted > (512 * FPM_MULTIPLIER * sd_diff)) { pblewanted -= 256 * FPM_MULTIPLIER * sd_diff; @@ -5043,7 +5035,7 @@ irdma_cfg_fpm_val(struct irdma_sc_dev *dev, u32 qp_count) if (sd_needed > max_sds) { irdma_debug(dev, IRDMA_DEBUG_HMC, - "cfg_fpm failed loop_cnt=%d, sd_needed=%d, max sd count %d\n", + "cfg_fpm failed loop_cnt=%u, sd_needed=%u, max sd count %u\n", loop_count, sd_needed, hmc_info->sd_table.sd_cnt); return -EINVAL; } @@ -5073,18 +5065,7 @@ irdma_cfg_fpm_val(struct irdma_sc_dev *dev, u32 qp_count) return ret_code; } - mem_size = sizeof(struct irdma_hmc_sd_entry) * - (hmc_info->sd_table.sd_cnt + hmc_info->first_sd_index + 1); - virt_mem.size = mem_size; - virt_mem.va = kzalloc(virt_mem.size, GFP_KERNEL); - if (!virt_mem.va) { - irdma_debug(dev, IRDMA_DEBUG_HMC, - "failed to allocate memory for sd_entry buffer\n"); - return -ENOMEM; - } - hmc_info->sd_table.sd_entry = virt_mem.va; - - return ret_code; + return irdma_cfg_sd_mem(dev, hmc_info); } /** @@ -5098,7 +5079,6 @@ irdma_exec_cqp_cmd(struct irdma_sc_dev *dev, { int status; struct irdma_dma_mem val_mem; - bool alloc = false; dev->cqp_cmd_stats[pcmdinfo->cqp_cmd]++; switch (pcmdinfo->cqp_cmd) { @@ -5204,15 +5184,6 @@ irdma_exec_cqp_cmd(struct irdma_sc_dev *dev, true, IRDMA_CQP_WAIT_EVENT); break; - case IRDMA_OP_STATS_ALLOCATE: - alloc = true; - /* fallthrough */ - case IRDMA_OP_STATS_FREE: - status = irdma_sc_manage_stats_inst(pcmdinfo->in.u.stats_manage.cqp, - &pcmdinfo->in.u.stats_manage.info, - alloc, - pcmdinfo->in.u.stats_manage.scratch); - break; case IRDMA_OP_STATS_GATHER: status = irdma_sc_gather_stats(pcmdinfo->in.u.stats_gather.cqp, &pcmdinfo->in.u.stats_gather.info, @@ -5381,6 +5352,7 @@ irdma_process_cqp_cmd(struct irdma_sc_dev *dev, status = irdma_exec_cqp_cmd(dev, pcmdinfo); else list_add_tail(&pcmdinfo->cqp_cmd_entry, &dev->cqp_cmd_head); + pcmdinfo->cqp_cmd_exec_status = status; spin_unlock_irqrestore(&dev->cqp_lock, flags); return status; } @@ -5389,7 +5361,7 @@ irdma_process_cqp_cmd(struct irdma_sc_dev *dev, * irdma_process_bh - called from tasklet for cqp list * @dev: sc device struct */ -int +void irdma_process_bh(struct irdma_sc_dev *dev) { int status = 0; @@ -5402,10 +5374,9 @@ irdma_process_bh(struct irdma_sc_dev *dev) pcmdinfo = (struct cqp_cmds_info *)irdma_remove_cqp_head(dev); status = irdma_exec_cqp_cmd(dev, pcmdinfo); if (status) - break; + pcmdinfo->cqp_cmd_exec_status = status; } spin_unlock_irqrestore(&dev->cqp_lock, flags); - return status; } /** @@ -5464,7 +5435,7 @@ irdma_wait_pe_ready(struct irdma_sc_dev *dev) if (statuscpu0 == 0x80 && statuscpu1 == 0x80 && statuscpu2 == 0x80) return 0; - mdelay(1000); + mdelay(100); } while (retrycount++ < dev->hw_attrs.max_pe_ready_count); return -1; } @@ -5566,9 +5537,9 @@ static inline u64 irdma_stat_val(const u64 *stats_val, u16 byteoff, static inline u64 irdma_stat_delta(u64 new_val, u64 old_val, u64 max_val) { if (new_val >= old_val) return new_val - old_val; - else - /* roll-over case */ - return max_val - old_val + new_val + 1; + + /* roll-over case */ + return max_val - old_val + new_val + 1; } /** diff --git a/sys/dev/irdma/irdma_defs.h b/sys/dev/irdma/irdma_defs.h index fd3bf82c9ad6..a4bed8d5f93d 100644 --- a/sys/dev/irdma/irdma_defs.h +++ b/sys/dev/irdma/irdma_defs.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2023 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -66,7 +66,6 @@ #define IRDMA_DSCP_NUM_VAL 64 #define IRDMA_MAX_TRAFFIC_CLASS 8 #define IRDMA_MAX_STATS_COUNT 128 -#define IRDMA_FIRST_NON_PF_STAT 4 #define IRDMA_MIN_MTU_IPV4 576 #define IRDMA_MIN_MTU_IPV6 1280 @@ -115,11 +114,31 @@ #define IRDMA_BYTE_200 200 #define IRDMA_BYTE_208 208 #define IRDMA_BYTE_216 216 +#define IRDMA_BYTE_224 224 +#define IRDMA_BYTE_232 232 +#define IRDMA_BYTE_240 240 +#define IRDMA_BYTE_248 248 +#define IRDMA_BYTE_256 256 +#define IRDMA_BYTE_264 264 +#define IRDMA_BYTE_272 272 +#define IRDMA_BYTE_280 280 +#define IRDMA_BYTE_288 288 +#define IRDMA_BYTE_296 296 +#define IRDMA_BYTE_304 304 +#define IRDMA_BYTE_312 312 +#define IRDMA_BYTE_320 320 +#define IRDMA_BYTE_328 328 +#define IRDMA_BYTE_336 336 +#define IRDMA_BYTE_344 344 +#define IRDMA_BYTE_352 352 +#define IRDMA_BYTE_360 360 +#define IRDMA_BYTE_368 368 +#define IRDMA_BYTE_376 376 +#define IRDMA_BYTE_384 384 #define IRDMA_CQP_WAIT_POLL_REGS 1 #define IRDMA_CQP_WAIT_POLL_CQ 2 #define IRDMA_CQP_WAIT_EVENT 3 - #define IRDMA_AE_SOURCE_RSVD 0x0 #define IRDMA_AE_SOURCE_RQ 0x1 #define IRDMA_AE_SOURCE_RQ_0011 0x3 @@ -157,8 +176,8 @@ #define IRDMA_TCP_STATE_RESERVED_3 14 #define IRDMA_TCP_STATE_RESERVED_4 15 -#define IRDMA_CQP_SW_SQSIZE_4 4 -#define IRDMA_CQP_SW_SQSIZE_2048 2048 +#define IRDMA_CQP_SW_SQSIZE_MIN 4 +#define IRDMA_CQP_SW_SQSIZE_MAX 2048 #define IRDMA_CQ_TYPE_IWARP 1 #define IRDMA_CQ_TYPE_ILQ 2 @@ -202,6 +221,8 @@ #define IRDMA_MAX_RQ_WQE_SHIFT_GEN1 2 #define IRDMA_MAX_RQ_WQE_SHIFT_GEN2 3 +#define IRDMA_DEFAULT_MAX_PUSH_LEN 8192 + #define IRDMA_SQ_RSVD 258 #define IRDMA_RQ_RSVD 1 @@ -222,6 +243,7 @@ #define IRDMAQP_OP_RDMA_READ_LOC_INV 0x0b #define IRDMAQP_OP_NOP 0x0c #define IRDMAQP_OP_RDMA_WRITE_SOL 0x0d + #define IRDMAQP_OP_GEN_RTS_AE 0x30 enum irdma_cqp_op_type { @@ -272,9 +294,9 @@ enum irdma_cqp_op_type { IRDMA_OP_ADD_LOCAL_MAC_ENTRY = 46, IRDMA_OP_DELETE_LOCAL_MAC_ENTRY = 47, IRDMA_OP_CQ_MODIFY = 48, - + IRDMA_OP_WS_MOVE = 49, /* Must be last entry */ - IRDMA_MAX_CQP_OPS = 49, + IRDMA_MAX_CQP_OPS = 50, }; /* CQP SQ WQES */ @@ -322,6 +344,7 @@ enum irdma_cqp_op_type { #define IRDMA_CQP_OP_MANAGE_STATS 0x2d #define IRDMA_CQP_OP_GATHER_STATS 0x2e #define IRDMA_CQP_OP_UP_MAP 0x2f +#define IRDMA_CQP_OP_MOVE_WS_NODES 0x34 #ifndef LS_64_1 #define LS_64_1(val, bits) ((u64)(uintptr_t)(val) << (bits)) @@ -420,6 +443,7 @@ enum irdma_cqp_op_type { #define IRDMA_CQPSQ_WS_VMVFNUM GENMASK_ULL(51, 42) #define IRDMA_CQPSQ_WS_OP_S 32 #define IRDMA_CQPSQ_WS_OP GENMASK_ULL(37, 32) +#define IRDMA_CQPSQ_WS_MOVE_OP GENMASK_ULL(37, 32) #define IRDMA_CQPSQ_WS_PARENTID_S 16 #define IRDMA_CQPSQ_WS_PARENTID GENMASK_ULL(25, 16) #define IRDMA_CQPSQ_WS_NODEID_S 0 @@ -493,6 +517,8 @@ enum irdma_cqp_op_type { #define IRDMA_CQPHC_EN_REM_ENDPOINT_TRK_S 3 #define IRDMA_CQPHC_EN_REM_ENDPOINT_TRK BIT_ULL(3) +#define IRDMA_CQPHC_TMR_SLOT_S 16 +#define IRDMA_CQPHC_TMR_SLOT GENMASK_ULL(19, 16) #define IRDMA_CQPHC_ENABLED_VFS_S 32 #define IRDMA_CQPHC_ENABLED_VFS GENMASK_ULL(37, 32) @@ -672,10 +698,10 @@ enum irdma_cqp_op_type { #define IRDMA_CQPSQ_QP_QPCTX IRDMA_CQPHC_QPCTX #define IRDMA_CQPSQ_QP_QPID_S 0 -#define IRDMA_CQPSQ_QP_QPID_M (0xFFFFFFUL) +#define IRDMA_CQPSQ_QP_QPID GENMASK_ULL(23, 0) #define IRDMA_CQPSQ_QP_OP_S 32 -#define IRDMA_CQPSQ_QP_OP_M IRDMACQ_OP_M +#define IRDMA_CQPSQ_QP_OP GENMASK_ULL(37, 32) #define IRDMA_CQPSQ_QP_ORDVALID_S 42 #define IRDMA_CQPSQ_QP_ORDVALID BIT_ULL(42) #define IRDMA_CQPSQ_QP_TOECTXVALID_S 43 @@ -751,6 +777,8 @@ enum irdma_cqp_op_type { #define IRDMA_CQPSQ_STAG_MR BIT_ULL(43) #define IRDMA_CQPSQ_STAG_MWTYPE_S 42 #define IRDMA_CQPSQ_STAG_MWTYPE BIT_ULL(42) +#define IRDMA_CQPSQ_STAG_SKIPFLUSH_S 40 +#define IRDMA_CQPSQ_STAG_SKIPFLUSH BIT_ULL(40) #define IRDMA_CQPSQ_STAG_MW1_BIND_DONT_VLDT_KEY_S 58 #define IRDMA_CQPSQ_STAG_MW1_BIND_DONT_VLDT_KEY BIT_ULL(58) @@ -767,8 +795,6 @@ enum irdma_cqp_op_type { #define IRDMA_CQPSQ_STAG_VABASEDTO BIT_ULL(59) #define IRDMA_CQPSQ_STAG_USEHMCFNIDX_S 60 #define IRDMA_CQPSQ_STAG_USEHMCFNIDX BIT_ULL(60) -#define IRDMA_CQPSQ_STAG_USEPFRID_S 61 -#define IRDMA_CQPSQ_STAG_USEPFRID BIT_ULL(61) #define IRDMA_CQPSQ_STAG_PBA_S IRDMA_CQPHC_QPCTX_S #define IRDMA_CQPSQ_STAG_PBA IRDMA_CQPHC_QPCTX @@ -882,12 +908,15 @@ enum irdma_cqp_op_type { #define IRDMA_CQPSQ_AEQ_FIRSTPMPBLIDX GENMASK_ULL(27, 0) #define IRDMA_COMMIT_FPM_QPCNT_S 0 -#define IRDMA_COMMIT_FPM_QPCNT GENMASK_ULL(18, 0) +#define IRDMA_COMMIT_FPM_QPCNT GENMASK_ULL(20, 0) #define IRDMA_COMMIT_FPM_BASE_S 32 #define IRDMA_CQPSQ_CFPM_HMCFNID_S 0 #define IRDMA_CQPSQ_CFPM_HMCFNID GENMASK_ULL(5, 0) +#define IRDMA_CQPSQ_CFPM_HW_FLUSH_TIMER_DISABLE_S 43 +#define IRDMA_CQPSQ_CFPM_HW_FLUSH_TIMER_DISABLE BIT_ULL(43) + #define IRDMA_CQPSQ_FWQE_AECODE_S 0 #define IRDMA_CQPSQ_FWQE_AECODE GENMASK_ULL(15, 0) #define IRDMA_CQPSQ_FWQE_AESOURCE_S 16 @@ -1123,9 +1152,9 @@ enum irdma_cqp_op_type { #define IRDMAQPC_RNRNAK_THRESH_S 54 #define IRDMAQPC_RNRNAK_THRESH GENMASK_ULL(56, 54) #define IRDMAQPC_TXCQNUM_S 0 -#define IRDMAQPC_TXCQNUM GENMASK_ULL(18, 0) +#define IRDMAQPC_TXCQNUM GENMASK_ULL(24, 0) #define IRDMAQPC_RXCQNUM_S 32 -#define IRDMAQPC_RXCQNUM GENMASK_ULL(50, 32) +#define IRDMAQPC_RXCQNUM GENMASK_ULL(56, 32) #define IRDMAQPC_STAT_INDEX_S 0 #define IRDMAQPC_STAT_INDEX GENMASK_ULL(6, 0) #define IRDMAQPC_Q2ADDR_S 8 @@ -1213,6 +1242,8 @@ enum irdma_cqp_op_type { #define IRDMA_FEATURE_TYPE GENMASK_ULL(63, 48) #define IRDMA_RSVD_S 41 #define IRDMA_RSVD GENMASK_ULL(55, 41) +#define IRDMA_FEATURE_RSRC_MAX_S 0 +#define IRDMA_FEATURE_RSRC_MAX GENMASK_ULL(31, 0) #define IRDMAQPSQ_OPCODE_S 32 #define IRDMAQPSQ_OPCODE GENMASK_ULL(37, 32) @@ -1258,7 +1289,7 @@ enum irdma_cqp_op_type { #define IRDMAQPSQ_DESTQPN_S 32 #define IRDMAQPSQ_DESTQPN GENMASK_ULL(55, 32) #define IRDMAQPSQ_AHID_S 0 -#define IRDMAQPSQ_AHID GENMASK_ULL(16, 0) +#define IRDMAQPSQ_AHID GENMASK_ULL(24, 0) #define IRDMAQPSQ_INLINEDATAFLAG_S 57 #define IRDMAQPSQ_INLINEDATAFLAG BIT_ULL(57) @@ -1347,7 +1378,7 @@ enum irdma_cqp_op_type { #define IRDMA_QUERY_FPM_FIRST_PE_SD_INDEX_S 0 #define IRDMA_QUERY_FPM_FIRST_PE_SD_INDEX GENMASK_ULL(13, 0) #define IRDMA_QUERY_FPM_MAX_PE_SDS_S 32 -#define IRDMA_QUERY_FPM_MAX_PE_SDS GENMASK_ULL(45, 32) +#define IRDMA_QUERY_FPM_MAX_PE_SDS GENMASK_ULL(44, 32) #define IRDMA_QUERY_FPM_MAX_CEQS_S 0 #define IRDMA_QUERY_FPM_MAX_CEQS GENMASK_ULL(9, 0) @@ -1422,9 +1453,9 @@ enum irdma_cqp_op_type { #define IRDMA_RING_MOVE_HEAD(_ring, _retcode) \ { \ u32 size; \ - size = (_ring).size; \ + size = IRDMA_RING_SIZE(_ring); \ if (!IRDMA_RING_FULL_ERR(_ring)) { \ - (_ring).head = ((_ring).head + 1) % size; \ + IRDMA_RING_CURRENT_HEAD(_ring) = (IRDMA_RING_CURRENT_HEAD(_ring) + 1) % size; \ (_retcode) = 0; \ } else { \ (_retcode) = -ENOSPC; \ @@ -1433,79 +1464,40 @@ enum irdma_cqp_op_type { #define IRDMA_RING_MOVE_HEAD_BY_COUNT(_ring, _count, _retcode) \ { \ u32 size; \ - size = (_ring).size; \ + size = IRDMA_RING_SIZE(_ring); \ if ((IRDMA_RING_USED_QUANTA(_ring) + (_count)) < size) { \ - (_ring).head = ((_ring).head + (_count)) % size; \ - (_retcode) = 0; \ - } else { \ - (_retcode) = -ENOSPC; \ - } \ - } -#define IRDMA_SQ_RING_MOVE_HEAD(_ring, _retcode) \ - { \ - u32 size; \ - size = (_ring).size; \ - if (!IRDMA_SQ_RING_FULL_ERR(_ring)) { \ - (_ring).head = ((_ring).head + 1) % size; \ - (_retcode) = 0; \ - } else { \ - (_retcode) = -ENOSPC; \ - } \ - } -#define IRDMA_SQ_RING_MOVE_HEAD_BY_COUNT(_ring, _count, _retcode) \ - { \ - u32 size; \ - size = (_ring).size; \ - if ((IRDMA_RING_USED_QUANTA(_ring) + (_count)) < (size - 256)) { \ - (_ring).head = ((_ring).head + (_count)) % size; \ + IRDMA_RING_CURRENT_HEAD(_ring) = (IRDMA_RING_CURRENT_HEAD(_ring) + (_count)) % size; \ (_retcode) = 0; \ } else { \ (_retcode) = -ENOSPC; \ } \ } -#define IRDMA_RING_MOVE_HEAD_BY_COUNT_NOCHECK(_ring, _count) \ - (_ring).head = ((_ring).head + (_count)) % (_ring).size -#define IRDMA_RING_MOVE_TAIL(_ring) \ - (_ring).tail = ((_ring).tail + 1) % (_ring).size +#define IRDMA_RING_MOVE_HEAD_BY_COUNT_NOCHECK(_ring, _count) \ + (IRDMA_RING_CURRENT_HEAD(_ring) = (IRDMA_RING_CURRENT_HEAD(_ring) + (_count)) % IRDMA_RING_SIZE(_ring)) #define IRDMA_RING_MOVE_HEAD_NOCHECK(_ring) \ - (_ring).head = ((_ring).head + 1) % (_ring).size + IRDMA_RING_MOVE_HEAD_BY_COUNT_NOCHECK(_ring, 1) #define IRDMA_RING_MOVE_TAIL_BY_COUNT(_ring, _count) \ - (_ring).tail = ((_ring).tail + (_count)) % (_ring).size + IRDMA_RING_CURRENT_TAIL(_ring) = (IRDMA_RING_CURRENT_TAIL(_ring) + (_count)) % IRDMA_RING_SIZE(_ring) + +#define IRDMA_RING_MOVE_TAIL(_ring) \ + IRDMA_RING_MOVE_TAIL_BY_COUNT(_ring, 1) #define IRDMA_RING_SET_TAIL(_ring, _pos) \ - (_ring).tail = (_pos) % (_ring).size + WRITE_ONCE(IRDMA_RING_CURRENT_TAIL(_ring), (_pos) % IRDMA_RING_SIZE(_ring)) #define IRDMA_RING_FULL_ERR(_ring) \ ( \ - (IRDMA_RING_USED_QUANTA(_ring) == ((_ring).size - 1)) \ - ) - -#define IRDMA_ERR_RING_FULL2(_ring) \ - ( \ - (IRDMA_RING_USED_QUANTA(_ring) == ((_ring).size - 2)) \ - ) - -#define IRDMA_ERR_RING_FULL3(_ring) \ - ( \ - (IRDMA_RING_USED_QUANTA(_ring) == ((_ring).size - 3)) \ + (IRDMA_RING_USED_QUANTA(_ring) == (IRDMA_RING_SIZE(_ring) - 1)) \ ) #define IRDMA_SQ_RING_FULL_ERR(_ring) \ ( \ - (IRDMA_RING_USED_QUANTA(_ring) == ((_ring).size - 257)) \ + (IRDMA_RING_USED_QUANTA(_ring) == (IRDMA_RING_SIZE(_ring) - 257)) \ ) -#define IRDMA_ERR_SQ_RING_FULL2(_ring) \ - ( \ - (IRDMA_RING_USED_QUANTA(_ring) == ((_ring).size - 258)) \ - ) -#define IRDMA_ERR_SQ_RING_FULL3(_ring) \ - ( \ - (IRDMA_RING_USED_QUANTA(_ring) == ((_ring).size - 259)) \ - ) #define IRDMA_RING_MORE_WORK(_ring) \ ( \ (IRDMA_RING_USED_QUANTA(_ring) != 0) \ @@ -1513,17 +1505,17 @@ enum irdma_cqp_op_type { #define IRDMA_RING_USED_QUANTA(_ring) \ ( \ - (((_ring).head + (_ring).size - (_ring).tail) % (_ring).size) \ + ((READ_ONCE(IRDMA_RING_CURRENT_HEAD(_ring)) + IRDMA_RING_SIZE(_ring) - READ_ONCE(IRDMA_RING_CURRENT_TAIL(_ring))) % IRDMA_RING_SIZE(_ring)) \ ) #define IRDMA_RING_FREE_QUANTA(_ring) \ ( \ - ((_ring).size - IRDMA_RING_USED_QUANTA(_ring) - 1) \ + (IRDMA_RING_SIZE(_ring) - IRDMA_RING_USED_QUANTA(_ring) - 1) \ ) #define IRDMA_SQ_RING_FREE_QUANTA(_ring) \ ( \ - ((_ring).size - IRDMA_RING_USED_QUANTA(_ring) - 257) \ + (IRDMA_RING_SIZE(_ring) - IRDMA_RING_USED_QUANTA(_ring) - 257) \ ) #define IRDMA_ATOMIC_RING_MOVE_HEAD(_ring, index, _retcode) \ diff --git a/sys/dev/irdma/irdma_hmc.c b/sys/dev/irdma/irdma_hmc.c index a3c47c8b1434..35c9373b9d86 100644 --- a/sys/dev/irdma/irdma_hmc.c +++ b/sys/dev/irdma/irdma_hmc.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2023 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -271,12 +271,18 @@ irdma_sc_create_hmc_obj(struct irdma_sc_dev *dev, bool pd_error = false; int ret_code = 0; - if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) + if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) { + irdma_debug(dev, IRDMA_DEBUG_ERR, + "invalid hmc obj type %u, start = %u, req cnt %u, cnt = %u\n", + info->rsrc_type, info->start_idx, info->count, + info->hmc_info->hmc_obj[info->rsrc_type].cnt); + return -EINVAL; + } if ((info->start_idx + info->count) > info->hmc_info->hmc_obj[info->rsrc_type].cnt) { - irdma_debug(dev, IRDMA_DEBUG_HMC, + irdma_debug(dev, IRDMA_DEBUG_ERR, "error type %u, start = %u, req cnt %u, cnt = %u\n", info->rsrc_type, info->start_idx, info->count, info->hmc_info->hmc_obj[info->rsrc_type].cnt); diff --git a/sys/dev/irdma/irdma_hw.c b/sys/dev/irdma/irdma_hw.c index 64c05b8663e0..9078a5a19b86 100644 --- a/sys/dev/irdma/irdma_hw.c +++ b/sys/dev/irdma/irdma_hw.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2025 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -147,8 +147,9 @@ irdma_process_ceq(struct irdma_pci_f *rf, struct irdma_ceq *ceq) sc_ceq = &ceq->sc_ceq; do { spin_lock_irqsave(&ceq->ce_lock, flags); + cq = irdma_sc_process_ceq(dev, sc_ceq); - if (!cq) { + if (!cq || rf->reset) { spin_unlock_irqrestore(&ceq->ce_lock, flags); break; } @@ -203,8 +204,10 @@ irdma_complete_cqp_request(struct irdma_cqp *cqp, /** * irdma_process_aeq - handle aeq events * @rf: RDMA PCI function + * + * Return: True if an AE was processed. */ -static void +static bool irdma_process_aeq(struct irdma_pci_f *rf) { struct irdma_sc_dev *dev = &rf->sc_dev; @@ -219,11 +222,10 @@ irdma_process_aeq(struct irdma_pci_f *rf) struct irdma_device *iwdev = rf->iwdev; struct irdma_qp_host_ctx_info *ctx_info = NULL; unsigned long flags; - u32 aeqcnt = 0; if (!sc_aeq->size) - return; + return false; do { memset(info, 0, sizeof(*info)); @@ -231,7 +233,16 @@ irdma_process_aeq(struct irdma_pci_f *rf) if (ret) break; + if (info->aeqe_overflow) { + irdma_dev_err(&iwdev->ibdev, "AEQ has overflowed\n"); + rf->reset = true; + rf->gen_ops.request_reset(rf); + return (aeqcnt > 0); + } + aeqcnt++; + atomic_inc(&iwdev->ae_info.ae_cnt); + irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_AEQ, "ae_id = 0x%x (%s), is_qp = %d, qp_id = %d, tcp_state = %d, iwarp_state = %d, ae_src = %d\n", info->ae_id, irdma_get_ae_desc(info->ae_id), @@ -265,8 +276,12 @@ irdma_process_aeq(struct irdma_pci_f *rf) spin_lock_irqsave(&iwqp->lock, flags); iwqp->hw_tcp_state = info->tcp_state; iwqp->hw_iwarp_state = info->iwarp_state; - if (info->ae_id != IRDMA_AE_QP_SUSPEND_COMPLETE) + + if (info->ae_id != IRDMA_AE_QP_SUSPEND_COMPLETE) { iwqp->last_aeq = info->ae_id; + iwqp->ae_src = info->ae_src; + } + spin_unlock_irqrestore(&iwqp->lock, flags); ctx_info = &iwqp->ctx_info; } else { @@ -397,10 +412,6 @@ irdma_process_aeq(struct irdma_pci_f *rf) case IRDMA_AE_LLP_TOO_MANY_RNRS: case IRDMA_AE_UDA_XMIT_DGRAM_TOO_LONG: default: - irdma_dev_err(&iwdev->ibdev, - "AEQ: abnormal ae_id = 0x%x (%s), is_qp = %d, qp_id = %d, ae_source = %d\n", - info->ae_id, irdma_get_ae_desc(info->ae_id), - info->qp, info->qp_cq_id, info->ae_src); if (rdma_protocol_roce(&iwqp->iwdev->ibdev, 1)) { ctx_info->roce_info->err_rq_idx_valid = info->err_rq_idx_valid; if (info->rq) { @@ -435,6 +446,8 @@ irdma_process_aeq(struct irdma_pci_f *rf) if (aeqcnt) irdma_sc_repost_aeq_entries(dev, aeqcnt); + + return (aeqcnt > 0); } /** @@ -449,11 +462,11 @@ irdma_ena_intr(struct irdma_sc_dev *dev, u32 msix_id) } /** - * irdma_dpc - tasklet for aeq and ceq 0 + * irdma_aeq_ceq0_tasklet_cb - tasklet for aeq and ceq 0 * @t: tasklet_struct ptr */ static void -irdma_dpc(unsigned long t) +irdma_aeq_ceq0_tasklet_cb(unsigned long t) { struct irdma_pci_f *rf = from_tasklet(rf, (struct tasklet_struct *)t, dpc_tasklet); @@ -465,11 +478,11 @@ irdma_dpc(unsigned long t) } /** - * irdma_ceq_dpc - dpc handler for CEQ + * irdma_ceq_tasklet_cb - tasklet handler for CEQ * @t: tasklet_struct ptr */ static void -irdma_ceq_dpc(unsigned long t) +irdma_ceq_tasklet_cb(unsigned long t) { struct irdma_ceq *iwceq = from_tasklet(iwceq, (struct tasklet_struct *)t, dpc_tasklet); @@ -502,7 +515,7 @@ irdma_save_msix_info(struct irdma_pci_f *rf) size = sizeof(struct irdma_msix_vector) * rf->msix_count; size += sizeof(*iw_qvlist); - size += sizeof(*iw_qvinfo) * rf->msix_count - 1; + size += sizeof(*iw_qvinfo) * (rf->msix_count - 1); rf->iw_msixtbl = kzalloc(size, GFP_KERNEL); if (!rf->iw_msixtbl) return -ENOMEM; @@ -538,11 +551,11 @@ irdma_save_msix_info(struct irdma_pci_f *rf) } /** - * irdma_irq_handler - interrupt handler for aeq and ceq0 + * irdma_aeq_ceq0_irq_handler - interrupt handler for aeq and ceq0 * @data: RDMA PCI function */ static void -irdma_irq_handler(void *data) +irdma_aeq_ceq0_irq_handler(void *data) { struct irdma_pci_f *rf = data; @@ -550,11 +563,11 @@ irdma_irq_handler(void *data) } /** - * irdma_ceq_handler - interrupt handler for ceq + * irdma_ceq_irq_handler - interrupt handler for ceq * @data: ceq pointer */ static void -irdma_ceq_handler(void *data) +irdma_ceq_irq_handler(void *data) { struct irdma_ceq *iwceq = data; @@ -625,8 +638,6 @@ irdma_destroy_cqp(struct irdma_pci_f *rf, bool free_hwcqp) struct irdma_cqp *cqp = &rf->cqp; int status = 0; - if (rf->cqp_cmpl_wq) - destroy_workqueue(rf->cqp_cmpl_wq); status = irdma_sc_cqp_destroy(dev->cqp, free_hwcqp); if (status) irdma_debug(dev, IRDMA_DEBUG_ERR, "Destroy CQP failed %d\n", status); @@ -794,6 +805,8 @@ irdma_destroy_ccq(struct irdma_pci_f *rf) struct irdma_ccq *ccq = &rf->ccq; int status = 0; + if (rf->cqp_cmpl_wq) + destroy_workqueue(rf->cqp_cmpl_wq); if (!rf->reset) status = irdma_sc_ccq_destroy(dev->ccq, 0, true); if (status) @@ -964,7 +977,7 @@ irdma_obj_aligned_mem(struct irdma_pci_f *rf, static int irdma_create_cqp(struct irdma_pci_f *rf) { - u32 sqsize = IRDMA_CQP_SW_SQSIZE_2048; + u32 sqsize = IRDMA_CQP_SW_SQSIZE_MAX; struct irdma_dma_mem mem; struct irdma_sc_dev *dev = &rf->sc_dev; struct irdma_cqp_init_info cqp_init_info = {0}; @@ -1012,6 +1025,7 @@ irdma_create_cqp(struct irdma_pci_f *rf) cqp_init_info.scratch_array = cqp->scratch_array; cqp_init_info.protocol_used = rf->protocol_used; cqp_init_info.en_rem_endpoint_trk = rf->en_rem_endpoint_trk; + cqp_init_info.timer_slots = rf->timer_slots; memcpy(&cqp_init_info.dcqcn_params, &rf->dcqcn_params, sizeof(cqp_init_info.dcqcn_params)); @@ -1077,12 +1091,13 @@ irdma_create_ccq(struct irdma_pci_f *rf) struct irdma_ccq_init_info info = {0}; struct irdma_ccq *ccq = &rf->ccq; int status; + int ccq_size = IW_CCQ_SIZE; dev->ccq = &ccq->sc_cq; dev->ccq->dev = dev; info.dev = dev; ccq->shadow_area.size = sizeof(struct irdma_cq_shadow_area); - ccq->mem_cq.size = sizeof(struct irdma_cqe) * IW_CCQ_SIZE; + ccq->mem_cq.size = sizeof(struct irdma_cqe) * ccq_size; ccq->mem_cq.va = irdma_allocate_dma_mem(dev->hw, &ccq->mem_cq, ccq->mem_cq.size, IRDMA_CQ0_ALIGNMENT); @@ -1099,7 +1114,7 @@ irdma_create_ccq(struct irdma_pci_f *rf) /* populate the ccq init info */ info.cq_base = ccq->mem_cq.va; info.cq_pa = ccq->mem_cq.pa; - info.num_elem = IW_CCQ_SIZE; + info.num_elem = ccq_size; info.shadow_area = ccq->shadow_area.va; info.shadow_area_pa = ccq->shadow_area.pa; info.ceqe_mask = false; @@ -1205,8 +1220,8 @@ irdma_cfg_ceq_vector(struct irdma_pci_f *rf, struct irdma_ceq *iwceq, if (rf->msix_shared && !ceq_id) { snprintf(msix_vec->name, sizeof(msix_vec->name) - 1, "irdma-%s-AEQCEQ-0", dev_name(&rf->pcidev->dev)); - tasklet_setup(&rf->dpc_tasklet, irdma_dpc); - status = irdma_irq_request(rf, msix_vec, irdma_irq_handler, rf); + tasklet_setup(&rf->dpc_tasklet, irdma_aeq_ceq0_tasklet_cb); + status = irdma_irq_request(rf, msix_vec, irdma_aeq_ceq0_irq_handler, rf); if (status) return status; bus_describe_intr(rf->dev_ctx.dev, msix_vec->res, msix_vec->tag, "%s", msix_vec->name); @@ -1214,9 +1229,9 @@ irdma_cfg_ceq_vector(struct irdma_pci_f *rf, struct irdma_ceq *iwceq, snprintf(msix_vec->name, sizeof(msix_vec->name) - 1, "irdma-%s-CEQ-%d", dev_name(&rf->pcidev->dev), ceq_id); - tasklet_setup(&iwceq->dpc_tasklet, irdma_ceq_dpc); + tasklet_setup(&iwceq->dpc_tasklet, irdma_ceq_tasklet_cb); - status = irdma_irq_request(rf, msix_vec, irdma_ceq_handler, iwceq); + status = irdma_irq_request(rf, msix_vec, irdma_ceq_irq_handler, iwceq); if (status) return status; bus_describe_intr(rf->dev_ctx.dev, msix_vec->res, msix_vec->tag, "%s", msix_vec->name); @@ -1243,8 +1258,8 @@ irdma_cfg_aeq_vector(struct irdma_pci_f *rf) if (!rf->msix_shared) { snprintf(msix_vec->name, sizeof(msix_vec->name) - 1, "irdma-%s-AEQ", dev_name(&rf->pcidev->dev)); - tasklet_setup(&rf->dpc_tasklet, irdma_dpc); - status = irdma_irq_request(rf, msix_vec, irdma_irq_handler, rf); + tasklet_setup(&rf->dpc_tasklet, irdma_aeq_ceq0_tasklet_cb); + status = irdma_irq_request(rf, msix_vec, irdma_aeq_ceq0_irq_handler, rf); if (status) return status; bus_describe_intr(rf->dev_ctx.dev, msix_vec->res, msix_vec->tag, "%s", msix_vec->name); @@ -1277,7 +1292,6 @@ irdma_create_ceq(struct irdma_pci_f *rf, struct irdma_ceq *iwceq, int status; struct irdma_ceq_init_info info = {0}; struct irdma_sc_dev *dev = &rf->sc_dev; - u64 scratch; u32 ceq_size; info.ceq_id = ceq_id; @@ -1300,14 +1314,13 @@ irdma_create_ceq(struct irdma_pci_f *rf, struct irdma_ceq *iwceq, iwceq->sc_ceq.ceq_id = ceq_id; info.dev = dev; info.vsi = vsi; - scratch = (uintptr_t)&rf->cqp.sc_cqp; status = irdma_sc_ceq_init(&iwceq->sc_ceq, &info); if (!status) { if (dev->ceq_valid) status = irdma_cqp_ceq_cmd(&rf->sc_dev, &iwceq->sc_ceq, IRDMA_OP_CEQ_CREATE); else - status = irdma_sc_cceq_create(&iwceq->sc_ceq, scratch); + status = irdma_sc_cceq_create(&iwceq->sc_ceq); } if (status) { @@ -1576,7 +1589,7 @@ irdma_initialize_ilq(struct irdma_device *iwdev) info.buf_size = 1024; info.tx_buf_cnt = 2 * info.sq_size; info.receive = irdma_receive_ilq; - info.xmit_complete = irdma_free_sqbuf; + info.xmit_complete = irdma_cm_ilq_cmpl_handler; status = irdma_puda_create_rsrc(&iwdev->vsi, &info); if (status) irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_ERR, "ilq create fail\n"); @@ -1827,6 +1840,16 @@ irdma_setup_init_state(struct irdma_pci_f *rf) if (status) goto clean_obj_mem; + /* + * Apply sysctl settings to max_hw_ird/ord + */ + rf->sc_dev.hw_attrs.max_hw_ird = irdma_sysctl_max_ird; + rf->sc_dev.hw_attrs.max_hw_ord = irdma_sysctl_max_ord; + irdma_debug(&rf->sc_dev, IRDMA_DEBUG_INIT, + "using max_hw_ird = %d and max_hw_ord = %d\n", + rf->sc_dev.hw_attrs.max_hw_ird, + rf->sc_dev.hw_attrs.max_hw_ord); + return 0; clean_obj_mem: @@ -2060,7 +2083,7 @@ irdma_ctrl_init_hw(struct irdma_pci_f *rf) break; rf->init_state = CEQ0_CREATED; /* Handles processing of CQP completions */ - rf->cqp_cmpl_wq = alloc_ordered_workqueue("cqp_cmpl_wq", + rf->cqp_cmpl_wq = alloc_ordered_workqueue("irdma-cqp_cmpl_wq", WQ_HIGHPRI | WQ_UNBOUND); if (!rf->cqp_cmpl_wq) { status = -ENOMEM; @@ -2373,6 +2396,7 @@ irdma_add_local_mac_entry(struct irdma_pci_f *rf, const u8 *mac_addr, u16 idx) cqp_info->cqp_cmd = IRDMA_OP_ADD_LOCAL_MAC_ENTRY; cqp_info->in.u.add_local_mac_entry.cqp = &iwcqp->sc_cqp; cqp_info->in.u.add_local_mac_entry.scratch = (uintptr_t)cqp_request; + cqp_info->create = true; status = irdma_handle_cqp_op(rf, cqp_request); irdma_put_cqp_request(iwcqp, cqp_request); @@ -2406,6 +2430,8 @@ irdma_alloc_local_mac_entry(struct irdma_pci_f *rf, u16 *mac_tbl_idx) cqp_info->post_sq = 1; cqp_info->in.u.alloc_local_mac_entry.cqp = &iwcqp->sc_cqp; cqp_info->in.u.alloc_local_mac_entry.scratch = (uintptr_t)cqp_request; + cqp_info->create = true; + status = irdma_handle_cqp_op(rf, cqp_request); if (!status) *mac_tbl_idx = (u16)cqp_request->compl_info.op_ret_val; @@ -2436,7 +2462,6 @@ irdma_cqp_manage_apbvt_cmd(struct irdma_device *iwdev, cqp_info = &cqp_request->info; info = &cqp_info->in.u.manage_apbvt_entry.info; - memset(info, 0, sizeof(*info)); info->add = add_port; info->port = accel_local_port; cqp_info->cqp_cmd = IRDMA_OP_MANAGE_APBVT_ENTRY; @@ -2519,35 +2544,22 @@ irdma_del_apbvt(struct irdma_device *iwdev, spin_unlock_irqrestore(&cm_core->apbvt_lock, flags); } -/** - * irdma_manage_arp_cache - manage hw arp cache - * @rf: RDMA PCI function - * @mac_addr: mac address ptr - * @ip_addr: ip addr for arp cache - * @action: add, delete or modify - */ void -irdma_manage_arp_cache(struct irdma_pci_f *rf, const unsigned char *mac_addr, - u32 *ip_addr, u32 action) +irdma_arp_cqp_op(struct irdma_pci_f *rf, u16 arp_index, + const unsigned char *mac_addr, u32 action) { struct irdma_add_arp_cache_entry_info *info; struct irdma_cqp_request *cqp_request; struct cqp_cmds_info *cqp_info; - int arp_index; - - arp_index = irdma_arp_table(rf, ip_addr, mac_addr, action); - if (arp_index == -1) - return; cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, false); if (!cqp_request) return; cqp_info = &cqp_request->info; - if (action == IRDMA_ARP_ADD) { + if (action == IRDMA_ARP_ADD_UPDATE) { cqp_info->cqp_cmd = IRDMA_OP_ADD_ARP_CACHE_ENTRY; info = &cqp_info->in.u.add_arp_cache_entry.info; - memset(info, 0, sizeof(*info)); info->arp_index = (u16)arp_index; info->permanent = true; ether_addr_copy(info->mac_addr, mac_addr); @@ -2568,6 +2580,26 @@ irdma_manage_arp_cache(struct irdma_pci_f *rf, const unsigned char *mac_addr, } /** + * irdma_manage_arp_cache - manage hw arp cache + * @rf: RDMA PCI function + * @mac_addr: mac address ptr + * @ip_addr: ip addr for arp cache + * @action: add, delete or modify + */ +void +irdma_manage_arp_cache(struct irdma_pci_f *rf, const unsigned char *mac_addr, + u32 *ip_addr, u32 action) +{ + int arp_index; + + arp_index = irdma_arp_table(rf, ip_addr, mac_addr, action); + if (arp_index == -1) + return; + + irdma_arp_cqp_op(rf, (u16)arp_index, mac_addr, action); +} + +/** * irdma_send_syn_cqp_callback - do syn/ack after qhash * @cqp_request: qhash cqp completion */ @@ -2577,7 +2609,7 @@ irdma_send_syn_cqp_callback(struct irdma_cqp_request *cqp_request) struct irdma_cm_node *cm_node = cqp_request->param; irdma_send_syn(cm_node, 1); - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); } /** @@ -2598,7 +2630,6 @@ irdma_qhash_info_prepare(struct irdma_device *iwdev, struct irdma_qhash_table_info *info; info = &cqp_info->in.u.manage_qhash_table_entry.info; - memset(info, 0, sizeof(*info)); info->vsi = &iwdev->vsi; info->manage = mtype; info->entry_type = etype; @@ -2731,7 +2762,7 @@ irdma_manage_qhash(struct irdma_device *iwdev, struct irdma_cm_info *cminfo, cqp_request->callback_fcn = irdma_send_syn_cqp_callback; cqp_request->param = cmnode; if (!wait) - atomic_inc(&cm_node->refcnt); + irdma_add_ref_cmnode(cm_node); } if (info->ipv4_valid) irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_CM, @@ -2759,7 +2790,7 @@ irdma_manage_qhash(struct irdma_device *iwdev, struct irdma_cm_info *cminfo, cqp_info->in.u.manage_qhash_table_entry.scratch = (uintptr_t)cqp_request; status = irdma_handle_cqp_op(iwdev->rf, cqp_request); if (status && cm_node && !wait) - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); irdma_put_cqp_request(iwcqp, cqp_request); @@ -2873,6 +2904,9 @@ irdma_flush_wqes(struct irdma_qp *iwqp, u32 flush_mask) if (!(flush_mask & IRDMA_FLUSH_SQ) && !(flush_mask & IRDMA_FLUSH_RQ)) return; + if (atomic_cmpxchg(&iwqp->flush_issued, 0, 1)) + return; + /* Set flush info fields */ info.sq = flush_mask & IRDMA_FLUSH_SQ; info.rq = flush_mask & IRDMA_FLUSH_RQ; @@ -2896,7 +2930,9 @@ irdma_flush_wqes(struct irdma_qp *iwqp, u32 flush_mask) if (info.rq && iwqp->sc_qp.rq_flush_code) info.rq_minor_code = flush_code; } - if (irdma_upload_context && irdma_upload_qp_context(iwqp, 0, 1)) + if (irdma_upload_context && + irdma_upload_qp_context(rf, iwqp->sc_qp.qp_uk.qp_id, + iwqp->sc_qp.qp_uk.qp_type, 0, 1)) irdma_dev_warn(&iwqp->iwdev->ibdev, "failed to upload QP context\n"); if (!iwqp->user_mode) irdma_sched_qp_flush_work(iwqp); @@ -2905,5 +2941,4 @@ irdma_flush_wqes(struct irdma_qp *iwqp, u32 flush_mask) /* Issue flush */ (void)irdma_hw_flush_wqes(rf, &iwqp->sc_qp, &info, flush_mask & IRDMA_FLUSH_WAIT); - iwqp->flush_issued = true; } diff --git a/sys/dev/irdma/irdma_kcompat.c b/sys/dev/irdma/irdma_kcompat.c index 4261fb45d390..51f44133252c 100644 --- a/sys/dev/irdma/irdma_kcompat.c +++ b/sys/dev/irdma/irdma_kcompat.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2018 - 2023 Intel Corporation + * Copyright (c) 2018 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -470,25 +470,49 @@ irdma_create_ah_wait(struct irdma_pci_f *rf, int ret; if (!sleep) { - int cnt = rf->sc_dev.hw_attrs.max_cqp_compl_wait_time_ms * - CQP_TIMEOUT_THRESHOLD; + bool timeout = false; + u64 start = get_jiffies_64(); + u64 completed_ops = atomic64_read(&rf->sc_dev.cqp->completed_ops); struct irdma_cqp_request *cqp_request = sc_ah->ah_info.cqp_request; + const u64 timeout_jiffies = + msecs_to_jiffies(rf->sc_dev.hw_attrs.max_cqp_compl_wait_time_ms * + CQP_TIMEOUT_THRESHOLD); + + /* + * NOTE: irdma_check_cqp_progress is not used here because it relies on a notion of a cycle count, but + * we want to avoid unnecessary delays. We are in an atomic context here, so we might as well check in + * a tight loop. + */ + while (!READ_ONCE(cqp_request->request_done)) { + u64 tmp; + u64 curr_jiffies; - do { irdma_cqp_ce_handler(rf, &rf->ccq.sc_cq); - mdelay(1); - } while (!READ_ONCE(cqp_request->request_done) && --cnt); - if (cnt && !cqp_request->compl_info.op_ret_val) { + curr_jiffies = get_jiffies_64(); + tmp = atomic64_read(&rf->sc_dev.cqp->completed_ops); + if (tmp != completed_ops) { + /* CQP is progressing. Reset timer. */ + completed_ops = tmp; + start = curr_jiffies; + } + + if ((curr_jiffies - start) > timeout_jiffies) { + timeout = true; + break; + } + } + + if (!timeout && !cqp_request->compl_info.op_ret_val) { irdma_put_cqp_request(&rf->cqp, cqp_request); sc_ah->ah_info.ah_valid = true; } else { - ret = !cnt ? -ETIMEDOUT : -EINVAL; + ret = timeout ? -ETIMEDOUT : -EINVAL; irdma_dev_err(&rf->iwdev->ibdev, "CQP create AH error ret = %d opt_ret_val = %d", ret, cqp_request->compl_info.op_ret_val); irdma_put_cqp_request(&rf->cqp, cqp_request); - if (!cnt && !rf->reset) { + if (timeout && !rf->reset) { rf->reset = true; rf->gen_ops.request_reset(rf); } @@ -501,19 +525,10 @@ irdma_create_ah_wait(struct irdma_pci_f *rf, #define IRDMA_CREATE_AH_MIN_RESP_LEN offsetofend(struct irdma_create_ah_resp, rsvd) -/** - * irdma_create_ah - create address handle - * @ib_ah: ptr to AH - * @attr: address handle attributes - * @flags: AH flags to wait - * @udata: user data - * - * returns 0 on success, error otherwise - */ -int -irdma_create_ah(struct ib_ah *ib_ah, - struct ib_ah_attr *attr, u32 flags, - struct ib_udata *udata) +static int +irdma_create_sleepable_ah(struct ib_ah *ib_ah, + struct ib_ah_attr *attr, u32 flags, + struct ib_udata *udata) { struct irdma_pd *pd = to_iwpd(ib_ah->pd); struct irdma_ah *ah = container_of(ib_ah, struct irdma_ah, ibah); @@ -613,6 +628,23 @@ err_gid_l2: return err; } +/** + * irdma_create_ah - create address handle + * @ib_ah: ptr to AH + * @attr: address handle attributes + * @flags: AH flags to wait + * @udata: user data + * + * returns 0 on success, error otherwise + */ +int +irdma_create_ah(struct ib_ah *ib_ah, + struct ib_ah_attr *attr, u32 flags, + struct ib_udata *udata) +{ + return irdma_create_sleepable_ah(ib_ah, attr, flags, udata); +} + void irdma_ether_copy(u8 *dmac, struct ib_ah_attr *attr) { @@ -691,6 +723,7 @@ irdma_create_qp(struct ib_pd *ibpd, struct irdma_uk_attrs *uk_attrs = &dev->hw_attrs.uk_attrs; struct irdma_qp_init_info init_info = {{0}}; struct irdma_qp_host_ctx_info *ctx_info; + u32 next_qp = 0; unsigned long flags; err_code = irdma_validate_qp_attrs(init_attr, iwdev); @@ -743,6 +776,9 @@ irdma_create_qp(struct ib_pd *ibpd, if (init_attr->qp_type == IB_QPT_GSI) qp_num = 1; + else if (dev->hw_attrs.uk_attrs.hw_rev <= IRDMA_GEN_2) + err_code = irdma_alloc_rsrc(rf, rf->allocated_qps, rf->max_qp, + &qp_num, &next_qp); else err_code = irdma_alloc_rsrc(rf, rf->allocated_qps, rf->max_qp, &qp_num, &rf->next_qp); @@ -759,7 +795,7 @@ irdma_create_qp(struct ib_pd *ibpd, iwqp->host_ctx.size = IRDMA_QP_CTX_SIZE; init_info.pd = &iwpd->sc_pd; - init_info.qp_uk_init_info.qp_id = iwqp->ibqp.qp_num; + init_info.qp_uk_init_info.qp_id = qp_num; if (!rdma_protocol_roce(&iwdev->ibdev, 1)) init_info.qp_uk_init_info.first_sq_wq = 1; iwqp->ctx_info.qp_compl_ctx = (uintptr_t)qp; @@ -769,10 +805,11 @@ irdma_create_qp(struct ib_pd *ibpd, spin_lock_init(&iwqp->dwork_flush_lock); if (udata) { + INIT_DELAYED_WORK(&iwqp->dwork_flush, irdma_user_flush_worker); init_info.qp_uk_init_info.abi_ver = iwpd->sc_pd.abi_ver; err_code = irdma_setup_umode_qp(udata, iwdev, iwqp, &init_info, init_attr); } else { - INIT_DELAYED_WORK(&iwqp->dwork_flush, irdma_flush_worker); + INIT_DELAYED_WORK(&iwqp->dwork_flush, irdma_kern_flush_worker); init_info.qp_uk_init_info.abi_ver = IRDMA_ABI_VER; err_code = irdma_setup_kmode_qp(iwdev, iwqp, &init_info, init_attr); } @@ -946,7 +983,6 @@ irdma_create_cq(struct ib_cq *ibcq, unsigned long flags; int err_code; int entries = attr->cqe; - bool cqe_64byte_ena; err_code = cq_validate_flags(attr->flags, dev->hw_attrs.uk_attrs.hw_rev); if (err_code) @@ -966,10 +1002,9 @@ irdma_create_cq(struct ib_cq *ibcq, INIT_LIST_HEAD(&iwcq->resize_list); INIT_LIST_HEAD(&iwcq->cmpl_generated); info.dev = dev; - ukinfo->cq_size = max(entries, 4); + ukinfo->cq_size = max_t(int, entries, 4); ukinfo->cq_id = cq_num; - cqe_64byte_ena = (dev->hw_attrs.uk_attrs.feature_flags & IRDMA_FEATURE_64_BYTE_CQE) ? true : false; - ukinfo->avoid_mem_cflct = cqe_64byte_ena; + iwcq->cq_num = cq_num; iwcq->ibcq.cqe = info.cq_uk_init_info.cq_size; atomic_set(&iwcq->armed, 0); if (attr->comp_vector < rf->ceqs_count) @@ -1004,8 +1039,6 @@ irdma_create_cq(struct ib_cq *ibcq, err_code = -EPROTO; goto cq_free_rsrc; } - iwcq->iwpbl = iwpbl; - iwcq->cq_mem_size = 0; cqmr = &iwpbl->cq_mr; if (rf->sc_dev.hw_attrs.uk_attrs.feature_flags & @@ -1019,7 +1052,6 @@ irdma_create_cq(struct ib_cq *ibcq, err_code = -EPROTO; goto cq_free_rsrc; } - iwcq->iwpbl_shadow = iwpbl_shadow; cqmr_shadow = &iwpbl_shadow->cq_mr; info.shadow_area_pa = cqmr_shadow->cq_pbl.addr; cqmr->split = true; @@ -1043,14 +1075,11 @@ irdma_create_cq(struct ib_cq *ibcq, } entries++; - if (!cqe_64byte_ena && dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) + if (dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_2) entries *= 2; ukinfo->cq_size = entries; - if (cqe_64byte_ena) - rsize = info.cq_uk_init_info.cq_size * sizeof(struct irdma_extended_cqe); - else - rsize = info.cq_uk_init_info.cq_size * sizeof(struct irdma_cqe); + rsize = info.cq_uk_init_info.cq_size * sizeof(struct irdma_cqe); iwcq->kmem.size = round_up(rsize, IRDMA_HW_PAGE_SIZE); iwcq->kmem.va = irdma_allocate_dma_mem(dev->hw, &iwcq->kmem, iwcq->kmem.size, IRDMA_HW_PAGE_SIZE); @@ -1094,6 +1123,7 @@ irdma_create_cq(struct ib_cq *ibcq, cqp_info->in.u.cq_create.cq = cq; cqp_info->in.u.cq_create.check_overflow = true; cqp_info->in.u.cq_create.scratch = (uintptr_t)cqp_request; + cqp_info->create = true; status = irdma_handle_cqp_op(rf, cqp_request); irdma_put_cqp_request(&rf->cqp, cqp_request); if (status) { @@ -1114,7 +1144,7 @@ irdma_create_cq(struct ib_cq *ibcq, } } - rf->cq_table[cq_num] = iwcq; + WRITE_ONCE(rf->cq_table[cq_num], iwcq); init_completion(&iwcq->free_cq); return 0; @@ -1227,6 +1257,86 @@ done: return 0; } +/** + * irdma_reg_user_mr - Register a user memory region + * @pd: ptr of pd + * @start: virtual start address + * @len: length of mr + * @virt: virtual address + * @access: access of mr + * @udata: user data + */ +struct ib_mr * +irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len, + u64 virt, int access, + struct ib_udata *udata) +{ +#define IRDMA_MEM_REG_MIN_REQ_LEN offsetofend(struct irdma_mem_reg_req, sq_pages) + struct irdma_device *iwdev = to_iwdev(pd->device); + struct irdma_mem_reg_req req = {}; + struct ib_umem *region; + struct irdma_mr *iwmr; + int err; + + if (len > iwdev->rf->sc_dev.hw_attrs.max_mr_size) + return ERR_PTR(-EINVAL); + + if (udata->inlen < IRDMA_MEM_REG_MIN_REQ_LEN) + return ERR_PTR(-EINVAL); + + region = ib_umem_get(pd->uobject->context, start, len, access, 0); + + if (IS_ERR(region)) { + irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_VERBS, + "Failed to create ib_umem region err=%ld\n", + PTR_ERR(region)); + return (struct ib_mr *)region; + } + + if (ib_copy_from_udata(&req, udata, min(sizeof(req), udata->inlen))) { + ib_umem_release(region); + return ERR_PTR(-EFAULT); + } + + iwmr = irdma_alloc_iwmr(region, pd, virt, req.reg_type); + if (IS_ERR(iwmr)) { + ib_umem_release(region); + return (struct ib_mr *)iwmr; + } + + switch (req.reg_type) { + case IRDMA_MEMREG_TYPE_QP: + err = irdma_reg_user_mr_type_qp(req, udata, iwmr); + if (err) + goto error; + + break; + case IRDMA_MEMREG_TYPE_CQ: + err = irdma_reg_user_mr_type_cq(req, udata, iwmr); + if (err) + goto error; + + break; + case IRDMA_MEMREG_TYPE_MEM: + err = irdma_reg_user_mr_type_mem(iwmr, access, true); + if (err) + goto error; + + break; + default: + err = -EINVAL; + goto error; + } + + return &iwmr->ibmr; + +error: + ib_umem_release(region); + irdma_free_iwmr(iwmr); + + return ERR_PTR(err); +} + /* * irdma_rereg_user_mr - Re-Register a user memory region @ibmr: ib mem to access iwarp mr pointer @flags: bit mask to * indicate which of the attr's of MR modified @start: virtual start address @len: length of mr @virt: virtual address @@ -1512,20 +1622,19 @@ irdma_query_port(struct ib_device *ibdev, u8 port, /* no need to zero out pros here. done by caller */ props->max_mtu = IB_MTU_4096; - props->active_mtu = ib_mtu_int_to_enum(if_getmtu(netdev)); + props->active_mtu = min(props->max_mtu, iboe_get_mtu(if_getmtu(netdev))); props->lid = 1; props->lmc = 0; props->sm_lid = 0; props->sm_sl = 0; - if ((if_getlinkstate(netdev) == LINK_STATE_UP) && - (if_getdrvflags(netdev) & IFF_DRV_RUNNING)) { + if ((if_getlinkstate(netdev) == LINK_STATE_UP) && (if_getdrvflags(netdev) & IFF_DRV_RUNNING)) { props->state = IB_PORT_ACTIVE; props->phys_state = IB_PORT_PHYS_STATE_LINK_UP; } else { props->state = IB_PORT_DOWN; props->phys_state = IB_PORT_PHYS_STATE_DISABLED; } - ib_get_eth_speed(ibdev, port, &props->active_speed, &props->active_width); + ib_get_eth_speed(ibdev, port, (u16 *)& props->active_speed, &props->active_width); if (rdma_protocol_roce(ibdev, 1)) { props->gid_tbl_len = 32; @@ -1720,36 +1829,104 @@ kc_set_rdma_uverbs_cmd_mask(struct irdma_device *iwdev) iwdev->ibdev.uverbs_ex_cmd_mask |= BIT_ULL(IB_USER_VERBS_EX_CMD_CREATE_CQ); } -int -ib_get_eth_speed(struct ib_device *ibdev, u32 port_num, u8 *speed, u8 *width) +static void +ib_get_width_and_speed(u32 netdev_speed, u32 lanes, + u16 *speed, u8 *width) { - if_t netdev = ibdev->get_netdev(ibdev, port_num); - u32 netdev_speed; + if (!lanes) { + if (netdev_speed <= SPEED_1000) { + *width = IB_WIDTH_1X; + *speed = IB_SPEED_SDR; + } else if (netdev_speed <= SPEED_10000) { + *width = IB_WIDTH_1X; + *speed = IB_SPEED_FDR10; + } else if (netdev_speed <= SPEED_20000) { + *width = IB_WIDTH_4X; + *speed = IB_SPEED_DDR; + } else if (netdev_speed <= SPEED_25000) { + *width = IB_WIDTH_1X; + *speed = IB_SPEED_EDR; + } else if (netdev_speed <= SPEED_40000) { + *width = IB_WIDTH_4X; + *speed = IB_SPEED_FDR10; + } else if (netdev_speed <= SPEED_50000) { + *width = IB_WIDTH_2X; + *speed = IB_SPEED_EDR; + } else if (netdev_speed <= SPEED_100000) { + *width = IB_WIDTH_4X; + *speed = IB_SPEED_EDR; + } else if (netdev_speed <= SPEED_200000) { + *width = IB_WIDTH_4X; + *speed = IB_SPEED_HDR; + } else { + *width = IB_WIDTH_4X; + *speed = IB_SPEED_NDR; + } - if (!netdev) - return -ENODEV; + return; + } - netdev_speed = if_getbaudrate(netdev); - dev_put(netdev); - if (netdev_speed <= SPEED_1000) { + switch (lanes) { + case 1: *width = IB_WIDTH_1X; - *speed = IB_SPEED_SDR; - } else if (netdev_speed <= SPEED_10000) { - *width = IB_WIDTH_1X; - *speed = IB_SPEED_FDR10; - } else if (netdev_speed <= SPEED_20000) { + break; + case 2: + *width = IB_WIDTH_2X; + break; + case 4: *width = IB_WIDTH_4X; - *speed = IB_SPEED_DDR; - } else if (netdev_speed <= SPEED_25000) { + break; + case 8: + *width = IB_WIDTH_8X; + break; + case 12: + *width = IB_WIDTH_12X; + break; + default: *width = IB_WIDTH_1X; - *speed = IB_SPEED_EDR; - } else if (netdev_speed <= SPEED_40000) { - *width = IB_WIDTH_4X; + } + + switch (netdev_speed / lanes) { + case SPEED_2500: + *speed = IB_SPEED_SDR; + break; + case SPEED_5000: + *speed = IB_SPEED_DDR; + break; + case SPEED_10000: *speed = IB_SPEED_FDR10; - } else { - *width = IB_WIDTH_4X; + break; + case SPEED_14000: + *speed = IB_SPEED_FDR; + break; + case SPEED_25000: *speed = IB_SPEED_EDR; + break; + case SPEED_50000: + *speed = IB_SPEED_HDR; + break; + case SPEED_100000: + *speed = IB_SPEED_NDR; + break; + default: + *speed = IB_SPEED_SDR; } +} + +int +ib_get_eth_speed(struct ib_device *ibdev, u32 port_num, u16 *speed, u8 *width) +{ + if_t netdev = ibdev->get_netdev(ibdev, port_num); + u32 netdev_speed, lanes; + + if (!netdev) + return -ENODEV; + + netdev_speed = (u32)if_getbaudrate(netdev); + dev_put(netdev); + lanes = 0; + + ib_get_width_and_speed(netdev_speed, lanes, speed, width); return 0; } diff --git a/sys/dev/irdma/irdma_main.h b/sys/dev/irdma/irdma_main.h index 9181f3b70463..1dc455532819 100644 --- a/sys/dev/irdma/irdma_main.h +++ b/sys/dev/irdma/irdma_main.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2025 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -74,16 +74,17 @@ extern bool irdma_upload_context; #define IRDMA_FW_VER_DEFAULT 2 #define IRDMA_HW_VER 2 -#define IRDMA_ARP_ADD 1 +#define IRDMA_ARP_ADD_UPDATE 1 +#define IRDMA_ARP_ADD IRDMA_ARP_ADD_UPDATE #define IRDMA_ARP_DELETE 2 #define IRDMA_ARP_RESOLVE 3 #define IRDMA_MACIP_ADD 1 #define IRDMA_MACIP_DELETE 2 -#define IW_CCQ_SIZE (IRDMA_CQP_SW_SQSIZE_2048 + 1) -#define IW_CEQ_SIZE 2048 -#define IW_AEQ_SIZE 2048 +#define IW_CCQ_SIZE (IRDMA_CQP_SW_SQSIZE_MAX + 2) +#define IW_CEQ_SIZE 2048 +#define IW_AEQ_SIZE 2048 #define RX_BUF_SIZE (1536 + 8) #define IW_REG0_SIZE (4 * 1024) @@ -96,6 +97,7 @@ extern bool irdma_upload_context; #define IRDMA_EVENT_TIMEOUT_MS 5000 #define IRDMA_VCHNL_EVENT_TIMEOUT_MS 10000 +#define IRDMA_RETRY_PRINT_MS 5000 #define IRDMA_RST_TIMEOUT_HZ 4 #define IRDMA_NO_QSET 0xffff @@ -107,7 +109,6 @@ extern bool irdma_upload_context; #define IRDMA_CQP_COMPL_SQ_WQE_FLUSHED 3 #define IRDMA_Q_TYPE_PE_AEQ 0x80 -#define IRDMA_Q_INVALID_IDX 0xffff #define IRDMA_REM_ENDPOINT_TRK_QPID 3 #define IRDMA_DRV_OPT_ENA_MPA_VER_0 0x00000001 @@ -228,6 +229,8 @@ struct irdma_aeq { struct irdma_arp_entry { u32 ip_addr[4]; u8 mac_addr[ETHER_ADDR_LEN]; + atomic_t refcnt; + bool delete_pending:1; }; struct irdma_msix_vector { @@ -314,6 +317,7 @@ struct irdma_pci_f { u32 next_ws_node_id; u32 max_ws_node_id; u32 limits_sel; + u8 timer_slots; unsigned long *allocated_ws_nodes; unsigned long *allocated_qps; unsigned long *allocated_cqs; @@ -351,8 +355,6 @@ struct irdma_pci_f { struct msix_entry msix_info; struct irdma_dma_mem obj_mem; struct irdma_dma_mem obj_next; - atomic_t vchnl_msgs; - wait_queue_head_t vchnl_waitq; struct workqueue_struct *cqp_cmpl_wq; struct work_struct cqp_cmpl_work; struct irdma_sc_vsi default_vsi; @@ -361,6 +363,15 @@ struct irdma_pci_f { void (*check_fc)(struct irdma_sc_vsi *vsi, struct irdma_sc_qp *sc_qp); struct irdma_dcqcn_cc_params dcqcn_params; struct irdma_device *iwdev; + struct delayed_work dwork_cqp_poll; + u32 chk_stag; +}; + +struct irdma_ae_info { + spinlock_t info_lock; + atomic_t ae_cnt; + u32 retry_cnt; + unsigned long retry_delay; }; struct irdma_device { @@ -372,6 +383,7 @@ struct irdma_device { struct workqueue_struct *cleanup_wq; struct irdma_sc_vsi vsi; struct irdma_cm_core cm_core; + struct irdma_ae_info ae_info; u32 roce_cwnd; u32 roce_ackcreds; u32 vendor_id; @@ -395,7 +407,6 @@ struct irdma_device { bool dcb_vlan_mode:1; bool iw_ooo:1; enum init_completion_state init_state; - wait_queue_head_t suspend_wq; }; @@ -522,6 +533,8 @@ void irdma_qp_rem_ref(struct ib_qp *ibqp); void irdma_free_lsmm_rsrc(struct irdma_qp *iwqp); struct ib_qp *irdma_get_qp(struct ib_device *ibdev, int qpn); void irdma_flush_wqes(struct irdma_qp *iwqp, u32 flush_mask); +void irdma_arp_cqp_op(struct irdma_pci_f *rf, u16 arp_index, + const unsigned char *mac_addr, u32 action); void irdma_manage_arp_cache(struct irdma_pci_f *rf, const unsigned char *mac_addr, u32 *ip_addr, u32 action); struct irdma_apbvt_entry *irdma_add_apbvt(struct irdma_device *iwdev, u16 port); @@ -555,6 +568,8 @@ void irdma_cq_add_ref(struct ib_cq *ibcq); void irdma_cq_rem_ref(struct ib_cq *ibcq); void irdma_cq_wq_destroy(struct irdma_pci_f *rf, struct irdma_sc_cq *cq); +void irdma_chk_free_stag(struct irdma_pci_f *rf); +void cqp_poll_worker(struct work_struct *work); void irdma_cleanup_pending_cqp_op(struct irdma_pci_f *rf); int irdma_hw_modify_qp(struct irdma_device *iwdev, struct irdma_qp *iwqp, struct irdma_modify_qp_info *info, bool wait); @@ -565,7 +580,7 @@ int irdma_manage_qhash(struct irdma_device *iwdev, struct irdma_cm_info *cminfo, bool wait); int irdma_add_qhash_wait_no_lock(struct irdma_device *iwdev, struct irdma_cm_info *cminfo); void irdma_receive_ilq(struct irdma_sc_vsi *vsi, struct irdma_puda_buf *rbuf); -void irdma_free_sqbuf(struct irdma_sc_vsi *vsi, void *bufp); +void irdma_cm_ilq_cmpl_handler(struct irdma_sc_vsi *vsi, void *bufp); void irdma_free_qp_rsrc(struct irdma_qp *iwqp); int irdma_setup_cm_core(struct irdma_device *iwdev, u8 ver); void irdma_cleanup_cm_core(struct irdma_cm_core *cm_core); @@ -586,8 +601,9 @@ u16 irdma_get_vlan_ipv4(struct iw_cm_id *cm_id, u32 *addr); void irdma_get_vlan_mac_ipv6(struct iw_cm_id *cm_id, u32 *addr, u16 *vlan_id, u8 *mac); struct ib_mr *irdma_reg_phys_mr(struct ib_pd *ib_pd, u64 addr, u64 size, - int acc, u64 *iova_start); -int irdma_upload_qp_context(struct irdma_qp *iwqp, bool freeze, bool raw); + int acc, u64 *iova_start, bool dma_mr); +int irdma_upload_qp_context(struct irdma_pci_f *rf, u32 qpn, + u8 qp_type, bool freeze, bool raw); void irdma_del_hmc_objects(struct irdma_sc_dev *dev, struct irdma_hmc_info *hmc_info, bool privileged, bool reset, enum irdma_vers vers); @@ -597,7 +613,6 @@ int irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd, void (*callback_fcn)(struct irdma_cqp_request *cqp_request), void *cb_param); void irdma_udqp_qs_worker(struct work_struct *work); -bool irdma_cq_empty(struct irdma_cq *iwcq); int irdma_netdevice_event(struct notifier_block *notifier, unsigned long event, void *ptr); void irdma_unregister_notifiers(struct irdma_device *iwdev); diff --git a/sys/dev/irdma/irdma_pble.c b/sys/dev/irdma/irdma_pble.c index aaf9d8917622..9d6d89b3f881 100644 --- a/sys/dev/irdma/irdma_pble.c +++ b/sys/dev/irdma/irdma_pble.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2023 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -108,7 +108,7 @@ static void get_sd_pd_idx(struct irdma_hmc_pble_rsrc *pble_rsrc, struct sd_pd_idx *idx) { - idx->sd_idx = (u32)pble_rsrc->next_fpm_addr / IRDMA_HMC_DIRECT_BP_SIZE; + idx->sd_idx = (u32)(pble_rsrc->next_fpm_addr / IRDMA_HMC_DIRECT_BP_SIZE); idx->pd_idx = (u32)(pble_rsrc->next_fpm_addr / IRDMA_HMC_PAGED_BP_SIZE); idx->rel_pd_idx = (idx->pd_idx % IRDMA_HMC_PD_CNT_IN_SD); } @@ -545,12 +545,14 @@ void irdma_free_pble(struct irdma_hmc_pble_rsrc *pble_rsrc, struct irdma_pble_alloc *palloc) { - pble_rsrc->freedpbles += palloc->total_cnt; - if (palloc->level == PBLE_LEVEL_2) free_lvl2(pble_rsrc, palloc); else irdma_prm_return_pbles(&pble_rsrc->pinfo, &palloc->level1.chunkinfo); + + mutex_lock(&pble_rsrc->pble_mutex_lock); + pble_rsrc->freedpbles += palloc->total_cnt; pble_rsrc->stats_alloc_freed++; + mutex_unlock(&pble_rsrc->pble_mutex_lock); } diff --git a/sys/dev/irdma/irdma_protos.h b/sys/dev/irdma/irdma_protos.h index 0663f9591d52..09a35e5a1f97 100644 --- a/sys/dev/irdma/irdma_protos.h +++ b/sys/dev/irdma/irdma_protos.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2016 - 2023 Intel Corporation + * Copyright (c) 2016 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -52,6 +52,7 @@ int irdma_sc_mr_fast_register(struct irdma_sc_qp *qp, bool post_sq); void irdma_init_config_check(struct irdma_config_check *cc, u8 traffic_class, + u8 prio, u16 qs_handle); /* HMC/FPM functions */ int irdma_sc_init_iw_hmc(struct irdma_sc_dev *dev, u16 hmc_fn_id); @@ -64,8 +65,6 @@ int irdma_cqp_ceq_cmd(struct irdma_sc_dev *dev, struct irdma_sc_ceq *sc_ceq, u8 op); int irdma_cqp_aeq_cmd(struct irdma_sc_dev *dev, struct irdma_sc_aeq *sc_aeq, u8 op); -int irdma_cqp_stats_inst_cmd(struct irdma_sc_vsi *vsi, u8 cmd, - struct irdma_stats_inst_info *stats_info); void irdma_update_stats(struct irdma_dev_hw_stats *hw_stats, struct irdma_gather_stats *gather_stats, struct irdma_gather_stats *last_gather_stats, @@ -115,7 +114,7 @@ int irdma_get_rdma_features(struct irdma_sc_dev *dev); void free_sd_mem(struct irdma_sc_dev *dev); int irdma_process_cqp_cmd(struct irdma_sc_dev *dev, struct cqp_cmds_info *pcmdinfo); -int irdma_process_bh(struct irdma_sc_dev *dev); +void irdma_process_bh(struct irdma_sc_dev *dev); extern void dump_ctx(struct irdma_sc_dev *dev, u32 pf_num, u32 qp_num); void dumpCSR(struct irdma_sc_dev *dev); void dumpCSRx(struct irdma_sc_dev *dev); diff --git a/sys/dev/irdma/irdma_puda.c b/sys/dev/irdma/irdma_puda.c index 0c5b9c164d76..5dc978259685 100644 --- a/sys/dev/irdma/irdma_puda.c +++ b/sys/dev/irdma/irdma_puda.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2023 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -435,6 +435,7 @@ irdma_puda_poll_cmpl(struct irdma_sc_dev *dev, struct irdma_sc_cq *cq, /* reusing so synch the buffer for CPU use */ dma_sync_single_for_cpu(hw_to_dev(dev->hw), buf->mem.pa, buf->mem.size, DMA_BIDIRECTIONAL); IRDMA_RING_SET_TAIL(qp->sq_ring, info.wqe_idx); + buf->queued = false; rsrc->xmit_complete(rsrc->vsi, buf); spin_lock_irqsave(&rsrc->bufpool_lock, flags); rsrc->tx_wqe_avail_cnt++; @@ -536,7 +537,7 @@ irdma_puda_send(struct irdma_sc_qp *qp, struct irdma_puda_send_info *info) * @rsrc: resource to use for buffer * @buf: puda buffer to transmit */ -void +int irdma_puda_send_buf(struct irdma_puda_rsrc *rsrc, struct irdma_puda_buf *buf) { @@ -545,17 +546,28 @@ irdma_puda_send_buf(struct irdma_puda_rsrc *rsrc, unsigned long flags; spin_lock_irqsave(&rsrc->bufpool_lock, flags); + if (buf) { + if (buf->queued) { + irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA, + "PUDA: Attempting to re-send queued buf %p\n", + buf); + spin_unlock_irqrestore(&rsrc->bufpool_lock, flags); + return -EINVAL; + } + + buf->queued = true; + } /* * if no wqe available or not from a completion and we have pending buffers, we must queue new buffer */ if (!rsrc->tx_wqe_avail_cnt || (buf && !list_empty(&rsrc->txpend))) { list_add_tail(&buf->list, &rsrc->txpend); - spin_unlock_irqrestore(&rsrc->bufpool_lock, flags); rsrc->stats_sent_pkt_q++; + spin_unlock_irqrestore(&rsrc->bufpool_lock, flags); if (rsrc->type == IRDMA_PUDA_RSRC_TYPE_ILQ) irdma_debug(rsrc->dev, IRDMA_DEBUG_PUDA, "adding to txpend\n"); - return; + return 0; } rsrc->tx_wqe_avail_cnt--; /* @@ -595,6 +607,7 @@ irdma_puda_send_buf(struct irdma_puda_rsrc *rsrc, } done: spin_unlock_irqrestore(&rsrc->bufpool_lock, flags); + return 0; } /** @@ -737,11 +750,14 @@ irdma_puda_qp_create(struct irdma_puda_rsrc *rsrc) irdma_qp_add_qos(qp); irdma_puda_qp_setctx(rsrc); + qp->qp_state = IRDMA_QP_STATE_RTS; + if (rsrc->dev->ceq_valid) ret = irdma_cqp_qp_create_cmd(rsrc->dev, qp); else ret = irdma_puda_qp_wqe(rsrc->dev, qp); if (ret) { + qp->qp_state = IRDMA_QP_STATE_INVALID; irdma_qp_rem_qos(qp); rsrc->dev->ws_remove(qp->vsi, qp->user_pri); irdma_free_dma_mem(rsrc->dev->hw, &rsrc->qpmem); @@ -964,6 +980,7 @@ irdma_puda_dele_rsrc(struct irdma_sc_vsi *vsi, enum puda_rsrc_type type, irdma_free_hash_desc(rsrc->hash_desc); /* fallthrough */ case PUDA_QP_CREATED: + rsrc->qp.qp_state = IRDMA_QP_STATE_INVALID; irdma_qp_rem_qos(&rsrc->qp); if (!reset) diff --git a/sys/dev/irdma/irdma_puda.h b/sys/dev/irdma/irdma_puda.h index aff435a90ecd..73e5c42f3c09 100644 --- a/sys/dev/irdma/irdma_puda.h +++ b/sys/dev/irdma/irdma_puda.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2022 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -94,20 +94,22 @@ struct irdma_puda_buf { u8 *iph; u8 *tcph; u8 *data; + u32 seqnum; + u32 ah_id; + u32 totallen; /* machlen+iphlen+tcphlen+datalen */ u16 datalen; u16 vlan_id; u8 tcphlen; /* tcp length in bytes */ u8 maclen; /* mac length in bytes */ - u32 totallen; /* machlen+iphlen+tcphlen+datalen */ - atomic_t refcount; + atomic_t pb_refcount; u8 hdrlen; bool virtdma:1; bool ipv4:1; bool vlan_valid:1; bool do_lpb:1; /* Loopback buffer */ bool smac_valid:1; - u32 seqnum; - u32 ah_id; + bool queued:1; + struct irdma_sc_ah *ah; u8 smac[ETHER_ADDR_LEN]; struct irdma_sc_vsi *vsi; }; @@ -184,7 +186,7 @@ struct irdma_puda_rsrc { struct irdma_puda_buf *irdma_puda_get_bufpool(struct irdma_puda_rsrc *rsrc); void irdma_puda_ret_bufpool(struct irdma_puda_rsrc *rsrc, struct irdma_puda_buf *buf); -void irdma_puda_send_buf(struct irdma_puda_rsrc *rsrc, +int irdma_puda_send_buf(struct irdma_puda_rsrc *rsrc, struct irdma_puda_buf *buf); int irdma_puda_send(struct irdma_sc_qp *qp, struct irdma_puda_send_info *info); int irdma_puda_create_rsrc(struct irdma_sc_vsi *vsi, diff --git a/sys/dev/irdma/irdma_type.h b/sys/dev/irdma/irdma_type.h index 011245f37779..77db328f940b 100644 --- a/sys/dev/irdma/irdma_type.h +++ b/sys/dev/irdma/irdma_type.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2023 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -279,6 +279,7 @@ struct irdma_cqp_init_info { u8 hmc_profile; u8 ena_vf_count; u8 ceqs_per_vf; + u8 timer_slots; bool en_datacenter_tcp:1; bool disable_packed:1; bool rocev2_rto_policy:1; @@ -414,6 +415,7 @@ struct irdma_sc_cqp { u8 ena_vf_count; u8 timeout_count; u8 ceqs_per_vf; + u8 timer_slots; bool en_datacenter_tcp:1; bool disable_packed:1; bool rocev2_rto_policy:1; @@ -442,8 +444,8 @@ struct irdma_sc_ceq { struct irdma_sc_dev *dev; struct irdma_ceqe *ceqe_base; void *pbl_list; - u32 ceq_id; u32 elem_cnt; + u16 ceq_id; struct irdma_ring ceq_ring; u8 pbl_chunk_size; u8 tph_val; @@ -466,8 +468,8 @@ struct irdma_sc_cq { struct irdma_sc_vsi *vsi; void *pbl_list; void *back_cq; - u32 ceq_id; u32 shadow_read_threshold; + u16 ceq_id; u8 pbl_chunk_size; u8 cq_type; u8 tph_val; @@ -505,6 +507,7 @@ struct irdma_sc_qp { u8 hw_sq_size; u8 hw_rq_size; u8 src_mac_addr_idx; + bool suspended:1; bool on_qoslist:1; bool ieq_pass_thru:1; bool sq_tph_en:1; @@ -523,12 +526,6 @@ struct irdma_sc_qp { struct list_head list; }; -struct irdma_stats_inst_info { - u16 hmc_fn_id; - u16 stats_idx; - bool use_hmc_fcn_index:1; -}; - struct irdma_up_info { u8 map[8]; u8 cnp_up_override; @@ -540,6 +537,13 @@ struct irdma_up_info { #define IRDMA_MAX_WS_NODES 0x3FF #define IRDMA_WS_NODE_INVALID 0xFFFF +struct irdma_ws_move_node_info { + u16 node_id[16]; + u8 num_nodes; + u8 target_port; + bool resume_traffic:1; +}; + struct irdma_ws_node_info { u16 id; u16 vsi; @@ -582,6 +586,7 @@ struct irdma_config_check { bool lfc_set:1; bool pfc_set:1; u8 traffic_class; + u8 prio; u16 qs_handle; }; @@ -599,7 +604,6 @@ struct irdma_sc_vsi { u32 exception_lan_q; u16 mtu; enum irdma_vm_vf_type vm_vf_type; - bool stats_inst_alloc:1; bool tc_change_pending:1; bool mtu_change_pending:1; struct irdma_vsi_pestat *pestat; @@ -653,7 +657,6 @@ struct irdma_sc_dev { u16 num_vfs; u16 hmc_fn_id; bool ceq_valid:1; - u8 pci_rev; int (*ws_add)(struct irdma_sc_vsi *vsi, u8 user_pri); void (*ws_remove)(struct irdma_sc_vsi *vsi, u8 user_pri); void (*ws_reset)(struct irdma_sc_vsi *vsi); @@ -773,7 +776,7 @@ struct irdma_ceq_init_info { u64 *ceqe_base; void *pbl_list; u32 elem_cnt; - u32 ceq_id; + u16 ceq_id; bool virtual_map:1; bool tph_en:1; bool itr_no_expire:1; @@ -804,8 +807,8 @@ struct irdma_ccq_init_info { __le64 *shadow_area; void *pbl_list; u32 num_elem; - u32 ceq_id; u32 shadow_read_threshold; + u16 ceq_id; bool ceqe_mask:1; bool ceq_id_valid:1; bool avoid_mem_cflct:1; @@ -1004,7 +1007,6 @@ struct irdma_allocate_stag_info { u16 access_rights; bool remote_access:1; bool use_hmc_fcn_index:1; - bool use_pf_rid:1; bool all_memory:1; u16 hmc_fcn_index; }; @@ -1032,7 +1034,6 @@ struct irdma_reg_ns_stag_info { irdma_stag_key stag_key; bool use_hmc_fcn_index:1; u16 hmc_fcn_index; - bool use_pf_rid:1; bool all_memory:1; }; @@ -1056,7 +1057,6 @@ struct irdma_fast_reg_stag_info { bool push_wqe:1; bool use_hmc_fcn_index:1; u16 hmc_fcn_index; - bool use_pf_rid:1; bool defer_flag:1; }; @@ -1065,6 +1065,7 @@ struct irdma_dealloc_stag_info { u32 pd_id; bool mr:1; bool dealloc_pbl:1; + bool skip_flush_markers:1; }; struct irdma_register_shared_stag { @@ -1102,8 +1103,8 @@ struct irdma_cq_init_info { struct irdma_sc_dev *dev; u64 cq_base_pa; u64 shadow_area_pa; - u32 ceq_id; u32 shadow_read_threshold; + u16 ceq_id; u8 pbl_chunk_size; u32 first_pm_pbl_idx; bool virtual_map:1; @@ -1204,7 +1205,7 @@ int irdma_sc_ccq_get_cqe_info(struct irdma_sc_cq *ccq, int irdma_sc_ccq_init(struct irdma_sc_cq *ccq, struct irdma_ccq_init_info *info); -int irdma_sc_cceq_create(struct irdma_sc_ceq *ceq, u64 scratch); +int irdma_sc_cceq_create(struct irdma_sc_ceq *ceq); int irdma_sc_cceq_destroy_done(struct irdma_sc_ceq *ceq); int irdma_sc_ceq_destroy(struct irdma_sc_ceq *ceq, u64 scratch, bool post_sq); @@ -1473,12 +1474,6 @@ struct cqp_info { struct { struct irdma_sc_cqp *cqp; - struct irdma_stats_inst_info info; - u64 scratch; - } stats_manage; - - struct { - struct irdma_sc_cqp *cqp; struct irdma_stats_gather_info info; u64 scratch; } stats_gather; @@ -1491,6 +1486,12 @@ struct cqp_info { struct { struct irdma_sc_cqp *cqp; + struct irdma_ws_move_node_info info; + u64 scratch; + } ws_move_node; + + struct { + struct irdma_sc_cqp *cqp; struct irdma_up_info info; u64 scratch; } up_map; @@ -1508,6 +1509,8 @@ struct cqp_cmds_info { u8 cqp_cmd; u8 post_sq; struct cqp_info in; + int cqp_cmd_exec_status; + bool create; }; __le64 *irdma_sc_cqp_get_next_send_wqe_idx(struct irdma_sc_cqp *cqp, u64 scratch, diff --git a/sys/dev/irdma/irdma_uda.h b/sys/dev/irdma/irdma_uda.h index 9850f986ee67..d21b811844af 100644 --- a/sys/dev/irdma/irdma_uda.h +++ b/sys/dev/irdma/irdma_uda.h @@ -44,6 +44,7 @@ struct irdma_sc_cqp; struct irdma_ah_info { struct irdma_sc_vsi *vsi; struct irdma_cqp_request *cqp_request; + atomic_t ah_refcnt; u32 pd_idx; u32 dst_arpindex; u32 dest_ip_addr[4]; @@ -63,6 +64,7 @@ struct irdma_ah_info { struct irdma_sc_ah { struct irdma_sc_dev *dev; struct irdma_ah_info ah_info; + struct work_struct ah_free_work; }; int irdma_sc_add_mcast_grp(struct irdma_mcast_grp_info *ctx, diff --git a/sys/dev/irdma/irdma_uda_d.h b/sys/dev/irdma/irdma_uda_d.h index bbf66bd8680d..1907abcecf12 100644 --- a/sys/dev/irdma/irdma_uda_d.h +++ b/sys/dev/irdma/irdma_uda_d.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2016 - 2021 Intel Corporation + * Copyright (c) 2016 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -183,6 +183,8 @@ #define IRDMA_UDA_CQPSQ_MAV_WQEVALID BIT_ULL(63) #define IRDMA_UDA_CQPSQ_MAV_OPCODE_S 32 #define IRDMA_UDA_CQPSQ_MAV_OPCODE GENMASK_ULL(37, 32) +#define IRDMA_UDA_CQPSQ_MAV_TYPE_S 53 +#define IRDMA_UDA_CQPSQ_MAV_TYPE GENMASK_ULL(54, 53) #define IRDMA_UDA_CQPSQ_MAV_DOLOOPBACKK_S 62 #define IRDMA_UDA_CQPSQ_MAV_DOLOOPBACKK BIT_ULL(62) #define IRDMA_UDA_CQPSQ_MAV_IPV4VALID_S 59 diff --git a/sys/dev/irdma/irdma_uk.c b/sys/dev/irdma/irdma_uk.c index 6c2e2dfb0031..cbe80fc59722 100644 --- a/sys/dev/irdma/irdma_uk.c +++ b/sys/dev/irdma/irdma_uk.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2023 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -133,16 +133,18 @@ irdma_nop_1(struct irdma_qp_uk *qp) void irdma_clr_wqes(struct irdma_qp_uk *qp, u32 qp_wqe_idx) { - __le64 *wqe; + struct irdma_qp_quanta *sq; u32 wqe_idx; if (!(qp_wqe_idx & 0x7F)) { wqe_idx = (qp_wqe_idx + 128) % qp->sq_ring.size; - wqe = qp->sq_base[wqe_idx].elem; + sq = qp->sq_base + wqe_idx; if (wqe_idx) - memset(wqe, qp->swqe_polarity ? 0 : 0xFF, 0x1000); + memset(sq, qp->swqe_polarity ? 0 : 0xFF, + 128 * sizeof(*sq)); else - memset(wqe, qp->swqe_polarity ? 0xFF : 0, 0x1000); + memset(sq, qp->swqe_polarity ? 0xFF : 0, + 128 * sizeof(*sq)); } } @@ -200,22 +202,65 @@ irdma_qp_ring_push_db(struct irdma_qp_uk *qp, u32 wqe_idx) qp->push_dropped = false; } +/** + * irdma_qp_push_wqe - setup push wqe and ring db + * @qp: hw qp ptr + * @wqe: wqe ptr + * @quanta: numbers of quanta in wqe + * @wqe_idx: wqe index + * @push_wqe: if to use push for the wqe + */ void irdma_qp_push_wqe(struct irdma_qp_uk *qp, __le64 * wqe, u16 quanta, - u32 wqe_idx, bool post_sq) + u32 wqe_idx, bool push_wqe) { __le64 *push; - if (IRDMA_RING_CURRENT_HEAD(qp->initial_ring) != - IRDMA_RING_CURRENT_TAIL(qp->sq_ring) && - !qp->push_mode) { - irdma_uk_qp_post_wr(qp); - } else { + if (push_wqe) { push = (__le64 *) ((uintptr_t)qp->push_wqe + (wqe_idx & 0x7) * 0x20); irdma_memcpy(push, wqe, quanta * IRDMA_QP_WQE_MIN_SIZE); irdma_qp_ring_push_db(qp, wqe_idx); + qp->last_push_db = true; + } else if (qp->last_push_db) { + qp->last_push_db = false; + db_wr32(qp->qp_id, qp->wqe_alloc_db); + } else { + irdma_uk_qp_post_wr(qp); + } +} + +/** + * irdma_push_ring_free - check if sq ring free to pust push wqe + * @qp: hw qp ptr + */ +static inline bool +irdma_push_ring_free(struct irdma_qp_uk *qp) +{ + u32 head, tail; + + head = IRDMA_RING_CURRENT_HEAD(qp->initial_ring); + tail = IRDMA_RING_CURRENT_TAIL(qp->sq_ring); + + if (head == tail || head == (tail + 1)) + return true; + + return false; +} + +/** + * irdma_enable_push_wqe - depending on sq ring and total size + * @qp: hw qp ptr + * @total_size: total data size + */ +static inline bool +irdma_enable_push_wqe(struct irdma_qp_uk *qp, u32 total_size) +{ + if (irdma_push_ring_free(qp) && + total_size <= qp->uk_attrs->max_hw_push_len) { + return true; } + return false; } /** @@ -234,7 +279,8 @@ irdma_qp_get_next_send_wqe(struct irdma_qp_uk *qp, u32 *wqe_idx, __le64 *wqe; __le64 *wqe_0 = NULL; u32 nop_wqe_idx; - u16 avail_quanta, wqe_quanta = *quanta; + u16 wqe_quanta = *quanta; + u16 avail_quanta; u16 i; avail_quanta = qp->uk_attrs->max_hw_sq_chunk - @@ -330,7 +376,7 @@ irdma_uk_rdma_write(struct irdma_qp_uk *qp, struct irdma_post_sq_info *info, bool read_fence = false; u16 quanta; - info->push_wqe = qp->push_db ? true : false; + info->push_wqe = false; op_info = &info->op.rdma_write; if (op_info->num_lo_sges > qp->max_sq_frag_cnt) @@ -350,11 +396,13 @@ irdma_uk_rdma_write(struct irdma_qp_uk *qp, struct irdma_post_sq_info *info, if (ret_code) return ret_code; + if (qp->push_db) + info->push_wqe = irdma_enable_push_wqe(qp, total_size); + wqe = irdma_qp_get_next_send_wqe(qp, &wqe_idx, &quanta, total_size, info); if (!wqe) return -ENOSPC; - qp->sq_wrtrk_array[wqe_idx].signaled = info->signaled; set_64bit_val(wqe, IRDMA_BYTE_16, FIELD_PREP(IRDMAQPSQ_FRAG_TO, op_info->rem_addr.addr)); @@ -399,8 +447,8 @@ irdma_uk_rdma_write(struct irdma_qp_uk *qp, struct irdma_post_sq_info *info, irdma_wmb(); /* make sure WQE is populated before valid bit is set */ set_64bit_val(wqe, IRDMA_BYTE_24, hdr); - if (info->push_wqe) - irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, post_sq); + if (qp->push_db) + irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, info->push_wqe); else if (post_sq) irdma_uk_qp_post_wr(qp); @@ -429,7 +477,7 @@ irdma_uk_rdma_read(struct irdma_qp_uk *qp, struct irdma_post_sq_info *info, u16 quanta; u64 hdr; - info->push_wqe = qp->push_db ? true : false; + info->push_wqe &= qp->push_db ? true : false; op_info = &info->op.rdma_read; if (qp->max_sq_frag_cnt < op_info->num_lo_sges) @@ -451,7 +499,6 @@ irdma_uk_rdma_read(struct irdma_qp_uk *qp, struct irdma_post_sq_info *info, qp->ord_cnt = 0; } - qp->sq_wrtrk_array[wqe_idx].signaled = info->signaled; addl_frag_cnt = op_info->num_lo_sges > 1 ? (op_info->num_lo_sges - 1) : 0; local_fence |= info->local_fence; @@ -490,8 +537,8 @@ irdma_uk_rdma_read(struct irdma_qp_uk *qp, struct irdma_post_sq_info *info, irdma_wmb(); /* make sure WQE is populated before valid bit is set */ set_64bit_val(wqe, IRDMA_BYTE_24, hdr); - if (info->push_wqe) - irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, post_sq); + if (qp->push_db) + irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, info->push_wqe); else if (post_sq) irdma_uk_qp_post_wr(qp); @@ -517,7 +564,7 @@ irdma_uk_send(struct irdma_qp_uk *qp, struct irdma_post_sq_info *info, bool read_fence = false; u16 quanta; - info->push_wqe = qp->push_db ? true : false; + info->push_wqe = false; op_info = &info->op.send; if (qp->max_sq_frag_cnt < op_info->num_sges) @@ -534,6 +581,9 @@ irdma_uk_send(struct irdma_qp_uk *qp, struct irdma_post_sq_info *info, if (ret_code) return ret_code; + if (qp->push_db) + info->push_wqe = irdma_enable_push_wqe(qp, total_size); + wqe = irdma_qp_get_next_send_wqe(qp, &wqe_idx, &quanta, total_size, info); if (!wqe) return -ENOSPC; @@ -587,8 +637,8 @@ irdma_uk_send(struct irdma_qp_uk *qp, struct irdma_post_sq_info *info, irdma_wmb(); /* make sure WQE is populated before valid bit is set */ set_64bit_val(wqe, IRDMA_BYTE_24, hdr); - if (info->push_wqe) - irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, post_sq); + if (qp->push_db) + irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, info->push_wqe); else if (post_sq) irdma_uk_qp_post_wr(qp); @@ -748,11 +798,11 @@ irdma_uk_inline_rdma_write(struct irdma_qp_uk *qp, return -EINVAL; quanta = qp->wqe_ops.iw_inline_data_size_to_quanta(total_size); + wqe = irdma_qp_get_next_send_wqe(qp, &wqe_idx, &quanta, total_size, info); if (!wqe) return -ENOSPC; - qp->sq_wrtrk_array[wqe_idx].signaled = info->signaled; read_fence |= info->read_fence; set_64bit_val(wqe, IRDMA_BYTE_16, FIELD_PREP(IRDMAQPSQ_FRAG_TO, op_info->rem_addr.addr)); @@ -780,8 +830,8 @@ irdma_uk_inline_rdma_write(struct irdma_qp_uk *qp, set_64bit_val(wqe, IRDMA_BYTE_24, hdr); - if (info->push_wqe) - irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, post_sq); + if (qp->push_db) + irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, info->push_wqe); else if (post_sq) irdma_uk_qp_post_wr(qp); @@ -854,8 +904,8 @@ irdma_uk_inline_send(struct irdma_qp_uk *qp, set_64bit_val(wqe, IRDMA_BYTE_24, hdr); - if (info->push_wqe) - irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, post_sq); + if (qp->push_db) + irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, info->push_wqe); else if (post_sq) irdma_uk_qp_post_wr(qp); @@ -905,8 +955,8 @@ irdma_uk_stag_local_invalidate(struct irdma_qp_uk *qp, set_64bit_val(wqe, IRDMA_BYTE_24, hdr); - if (info->push_wqe) - irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, post_sq); + if (qp->push_db) + irdma_qp_push_wqe(qp, wqe, quanta, wqe_idx, info->push_wqe); else if (post_sq) irdma_uk_qp_post_wr(qp); @@ -1065,29 +1115,6 @@ irdma_check_rq_cqe(struct irdma_qp_uk *qp, u32 *array_idx) } /** - * irdma_skip_duplicate_flush_cmpl - check last cmpl and update wqe if needed - * - * @ring: sq/rq ring - * @flush_seen: information if flush for specific ring was already seen - * @comp_status: completion status - * @wqe_idx: new value of WQE index returned if there is more work on ring - */ -static inline int -irdma_skip_duplicate_flush_cmpl(struct irdma_ring ring, u8 flush_seen, - enum irdma_cmpl_status comp_status, - u32 *wqe_idx) -{ - if (flush_seen) { - if (IRDMA_RING_MORE_WORK(ring)) - *wqe_idx = ring.tail; - else - return -ENOENT; - } - - return 0; -} - -/** * irdma_detect_unsignaled_cmpls - check if unsignaled cmpl is to be reported * @cq: hw cq * @qp: hw qp @@ -1140,6 +1167,28 @@ irdma_detect_unsignaled_cmpls(struct irdma_cq_uk *cq, } /** + * irdma_uk_cq_empty - Check if CQ is empty + * @cq: hw cq + */ +bool +irdma_uk_cq_empty(struct irdma_cq_uk *cq) +{ + __le64 *cqe; + u8 polarity; + u64 qword3; + + if (cq->avoid_mem_cflct) + cqe = IRDMA_GET_CURRENT_EXTENDED_CQ_ELEM(cq); + else + cqe = IRDMA_GET_CURRENT_CQ_ELEM(cq); + + get_64bit_val(cqe, 24, &qword3); + polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword3); + + return polarity != cq->polarity; +} + +/** * irdma_uk_cq_poll_cmpl - get cq completion info * @cq: hw cq * @info: cq poll information returned @@ -1158,6 +1207,7 @@ irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, u8 polarity; bool ext_valid; __le64 *ext_cqe; + unsigned long flags; if (cq->avoid_mem_cflct) cqe = IRDMA_GET_CURRENT_EXTENDED_CQ_ELEM(cq); @@ -1229,6 +1279,10 @@ irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, info->ipv4 = (bool)FIELD_GET(IRDMACQ_IPV4, qword3); get_64bit_val(cqe, IRDMA_BYTE_8, &comp_ctx); qp = (struct irdma_qp_uk *)(irdma_uintptr) comp_ctx; + if (!qp || qp->destroy_pending) { + ret_code = -EFAULT; + goto exit; + } if (info->error) { info->major_err = FIELD_GET(IRDMA_CQ_MAJERR, qword3); info->minor_err = FIELD_GET(IRDMA_CQ_MINERR, qword3); @@ -1253,15 +1307,10 @@ irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, get_64bit_val(cqe, IRDMA_BYTE_0, &qword0); get_64bit_val(cqe, IRDMA_BYTE_16, &qword2); - info->stat.raw = (u32)FIELD_GET(IRDMACQ_TCPSQN_ROCEPSN_RTT_TS, qword0); info->qp_id = (u32)FIELD_GET(IRDMACQ_QPID, qword2); info->ud_src_qpn = (u32)FIELD_GET(IRDMACQ_UDSRCQPN, qword2); info->solicited_event = (bool)FIELD_GET(IRDMACQ_SOEVENT, qword3); - if (!qp || qp->destroy_pending) { - ret_code = -EFAULT; - goto exit; - } wqe_idx = (u32)FIELD_GET(IRDMA_CQ_WQEIDX, qword3); info->qp_handle = (irdma_qp_handle) (irdma_uintptr) qp; info->op_type = (u8)FIELD_GET(IRDMACQ_OP, qword3); @@ -1269,51 +1318,42 @@ irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, if (info->q_type == IRDMA_CQE_QTYPE_RQ) { u32 array_idx; - ret_code = irdma_skip_duplicate_flush_cmpl(qp->rq_ring, - qp->rq_flush_seen, - info->comp_status, - &wqe_idx); - if (ret_code != 0) - goto exit; - array_idx = wqe_idx / qp->rq_wqe_size_multiplier; + info->bytes_xfered = (u32)FIELD_GET(IRDMACQ_PAYLDLEN, qword0); + info->signaled = 1; + + if (qword3 & IRDMACQ_STAG) { + info->stag_invalid_set = true; + info->inv_stag = (u32)FIELD_GET(IRDMACQ_INVSTAG, qword2); + } else { + info->stag_invalid_set = false; + } if (info->comp_status == IRDMA_COMPL_STATUS_FLUSHED || info->comp_status == IRDMA_COMPL_STATUS_UNKNOWN) { + spin_lock_irqsave(qp->lock, flags); if (!IRDMA_RING_MORE_WORK(qp->rq_ring)) { ret_code = -ENOENT; + spin_unlock_irqrestore(qp->lock, flags); goto exit; } info->wr_id = qp->rq_wrid_array[qp->rq_ring.tail]; - info->signaled = 1; - array_idx = qp->rq_ring.tail; + IRDMA_RING_SET_TAIL(qp->rq_ring, qp->rq_ring.tail + 1); + if (!IRDMA_RING_MORE_WORK(qp->rq_ring)) + qp->rq_flush_complete = true; + else + move_cq_head = false; + spin_unlock_irqrestore(qp->lock, flags); } else { info->wr_id = qp->rq_wrid_array[array_idx]; - info->signaled = 1; if (irdma_check_rq_cqe(qp, &array_idx)) { info->wr_id = qp->rq_wrid_array[array_idx]; info->comp_status = IRDMA_COMPL_STATUS_UNKNOWN; IRDMA_RING_SET_TAIL(qp->rq_ring, array_idx + 1); return 0; } - } - - info->bytes_xfered = (u32)FIELD_GET(IRDMACQ_PAYLDLEN, qword0); - - if (qword3 & IRDMACQ_STAG) { - info->stag_invalid_set = true; - info->inv_stag = (u32)FIELD_GET(IRDMACQ_INVSTAG, qword2); - } else { - info->stag_invalid_set = false; - } - IRDMA_RING_SET_TAIL(qp->rq_ring, array_idx + 1); - if (info->comp_status == IRDMA_COMPL_STATUS_FLUSHED) { - qp->rq_flush_seen = true; - if (!IRDMA_RING_MORE_WORK(qp->rq_ring)) - qp->rq_flush_complete = true; - else - move_cq_head = false; + IRDMA_RING_SET_TAIL(qp->rq_ring, array_idx + 1); } pring = &qp->rq_ring; } else { /* q_type is IRDMA_CQE_QTYPE_SQ */ @@ -1335,12 +1375,6 @@ irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, qp->push_mode = false; qp->push_dropped = true; } - ret_code = irdma_skip_duplicate_flush_cmpl(qp->sq_ring, - qp->sq_flush_seen, - info->comp_status, - &wqe_idx); - if (ret_code != 0) - goto exit; if (info->comp_status != IRDMA_COMPL_STATUS_FLUSHED) { info->wr_id = qp->sq_wrtrk_array[wqe_idx].wrid; info->signaled = qp->sq_wrtrk_array[wqe_idx].signaled; @@ -1353,8 +1387,6 @@ irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, IRDMA_RING_SET_TAIL(qp->sq_ring, wqe_idx + qp->sq_wrtrk_array[wqe_idx].quanta); } else { - unsigned long flags; - spin_lock_irqsave(qp->lock, flags); if (!IRDMA_RING_MORE_WORK(qp->sq_ring)) { spin_unlock_irqrestore(qp->lock, flags); @@ -1386,7 +1418,6 @@ irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, if (info->op_type == IRDMA_OP_TYPE_BIND_MW && info->minor_err == FLUSH_PROT_ERR) info->minor_err = FLUSH_MW_BIND_ERR; - qp->sq_flush_seen = true; if (!IRDMA_RING_MORE_WORK(qp->sq_ring)) qp->sq_flush_complete = true; spin_unlock_irqrestore(qp->lock, flags); @@ -1416,8 +1447,9 @@ exit: IRDMA_RING_MOVE_TAIL(cq->cq_ring); if (!cq->avoid_mem_cflct && ext_valid) IRDMA_RING_MOVE_TAIL(cq->cq_ring); - set_64bit_val(cq->shadow_area, IRDMA_BYTE_0, - IRDMA_RING_CURRENT_HEAD(cq->cq_ring)); + if (IRDMA_RING_CURRENT_HEAD(cq->cq_ring) & 0x3F || irdma_uk_cq_empty(cq)) + set_64bit_val(cq->shadow_area, IRDMA_BYTE_0, + IRDMA_RING_CURRENT_HEAD(cq->cq_ring)); } else { qword3 &= ~IRDMA_CQ_WQEIDX; qword3 |= FIELD_PREP(IRDMA_CQ_WQEIDX, pring->tail); @@ -1482,15 +1514,16 @@ irdma_get_wqe_shift(struct irdma_uk_attrs *uk_attrs, u32 sge, int irdma_get_sqdepth(struct irdma_uk_attrs *uk_attrs, u32 sq_size, u8 shift, u32 *sqdepth) { - u32 min_size = (u32)uk_attrs->min_hw_wq_size << shift; - - *sqdepth = irdma_round_up_wq((sq_size << shift) + IRDMA_SQ_RSVD); + u32 min_hw_quanta = (u32)uk_attrs->min_hw_wq_size << shift; + u64 hw_quanta = + irdma_round_up_wq(((u64)sq_size << shift) + IRDMA_SQ_RSVD); - if (*sqdepth < min_size) - *sqdepth = min_size; - else if (*sqdepth > uk_attrs->max_hw_wq_quanta) + if (hw_quanta < min_hw_quanta) + hw_quanta = min_hw_quanta; + else if (hw_quanta > uk_attrs->max_hw_wq_quanta) return -EINVAL; + *sqdepth = hw_quanta; return 0; } @@ -1501,15 +1534,16 @@ irdma_get_sqdepth(struct irdma_uk_attrs *uk_attrs, u32 sq_size, u8 shift, u32 *s int irdma_get_rqdepth(struct irdma_uk_attrs *uk_attrs, u32 rq_size, u8 shift, u32 *rqdepth) { - u32 min_size = (u32)uk_attrs->min_hw_wq_size << shift; - - *rqdepth = irdma_round_up_wq((rq_size << shift) + IRDMA_RQ_RSVD); + u32 min_hw_quanta = (u32)uk_attrs->min_hw_wq_size << shift; + u64 hw_quanta = + irdma_round_up_wq(((u64)rq_size << shift) + IRDMA_RQ_RSVD); - if (*rqdepth < min_size) - *rqdepth = min_size; - else if (*rqdepth > uk_attrs->max_hw_rq_quanta) + if (hw_quanta < min_hw_quanta) + hw_quanta = min_hw_quanta; + else if (hw_quanta > uk_attrs->max_hw_rq_quanta) return -EINVAL; + *rqdepth = hw_quanta; return 0; } diff --git a/sys/dev/irdma/irdma_user.h b/sys/dev/irdma/irdma_user.h index 05828ebbd7d6..71b08d9d486d 100644 --- a/sys/dev/irdma/irdma_user.h +++ b/sys/dev/irdma/irdma_user.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2023 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -184,12 +184,10 @@ enum irdma_device_caps_const { IRDMA_MIN_IW_QP_ID = 0, IRDMA_QUERY_FPM_BUF_SIZE = 176, IRDMA_COMMIT_FPM_BUF_SIZE = 176, - IRDMA_MAX_IW_QP_ID = 262143, IRDMA_MIN_CEQID = 0, IRDMA_MAX_CEQID = 1023, IRDMA_CEQ_MAX_COUNT = IRDMA_MAX_CEQID + 1, IRDMA_MIN_CQID = 0, - IRDMA_MAX_CQID = 524287, IRDMA_MIN_AEQ_ENTRIES = 1, IRDMA_MAX_AEQ_ENTRIES = 524287, IRDMA_MIN_CEQ_ENTRIES = 1, @@ -284,7 +282,7 @@ struct irdma_cq_uk_init_info; struct irdma_ring { volatile u32 head; - volatile u32 tail; /* effective tail */ + volatile u32 tail; u32 size; }; @@ -385,12 +383,6 @@ struct irdma_cq_poll_info { bool ud_smac_valid:1; bool imm_valid:1; bool signaled:1; - union { - u32 tcp_sqn; - u32 roce_psn; - u32 rtt; - u32 raw; - } stat; }; struct qp_err_code { @@ -426,6 +418,7 @@ struct irdma_wqe_uk_ops { struct irdma_bind_window *op_info); }; +bool irdma_uk_cq_empty(struct irdma_cq_uk *cq); int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq, struct irdma_cq_poll_info *info); void irdma_uk_cq_request_notification(struct irdma_cq_uk *cq, @@ -465,6 +458,8 @@ struct irdma_qp_uk { __le64 *shadow_area; __le32 *push_db; __le64 *push_wqe; + void *push_db_map; + void *push_wqe_map; struct irdma_ring sq_ring; struct irdma_ring sq_sig_ring; struct irdma_ring rq_ring; @@ -494,12 +489,11 @@ struct irdma_qp_uk { bool sq_flush_complete:1; /* Indicates flush was seen and SQ was empty after the flush */ bool rq_flush_complete:1; /* Indicates flush was seen and RQ was empty after the flush */ bool destroy_pending:1; /* Indicates the QP is being destroyed */ + bool last_push_db:1; /* Indicates last DB was push DB */ void *back_qp; spinlock_t *lock; u8 dbg_rq_flushed; u16 ord_cnt; - u8 sq_flush_seen; - u8 rq_flush_seen; u8 rd_fence_rate; }; @@ -563,10 +557,12 @@ int irdma_fragcnt_to_quanta_sq(u32 frag_cnt, u16 *quanta); int irdma_fragcnt_to_wqesize_rq(u32 frag_cnt, u16 *wqe_size); void irdma_get_wqe_shift(struct irdma_uk_attrs *uk_attrs, u32 sge, u32 inline_data, u8 *shift); -int irdma_get_sqdepth(struct irdma_uk_attrs *uk_attrs, u32 sq_size, u8 shift, u32 *sqdepth); -int irdma_get_rqdepth(struct irdma_uk_attrs *uk_attrs, u32 rq_size, u8 shift, u32 *rqdepth); +int irdma_get_sqdepth(struct irdma_uk_attrs *uk_attrs, u32 sq_size, + u8 shift, u32 *sqdepth); +int irdma_get_rqdepth(struct irdma_uk_attrs *uk_attrs, u32 rq_size, + u8 shift, u32 *rqdepth); void irdma_qp_push_wqe(struct irdma_qp_uk *qp, __le64 *wqe, u16 quanta, - u32 wqe_idx, bool post_sq); + u32 wqe_idx, bool push_wqe); void irdma_clr_wqes(struct irdma_qp_uk *qp, u32 qp_wqe_idx); static inline struct qp_err_code irdma_ae_to_qp_err_code(u16 ae_id) diff --git a/sys/dev/irdma/irdma_utils.c b/sys/dev/irdma/irdma_utils.c index 038f1980082b..ef8cb38d8139 100644 --- a/sys/dev/irdma/irdma_utils.c +++ b/sys/dev/irdma/irdma_utils.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2023 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -37,6 +37,7 @@ LIST_HEAD(irdma_handlers); DEFINE_SPINLOCK(irdma_handler_lock); +static const char *const irdma_cqp_cmd_names[IRDMA_MAX_CQP_OPS]; static const struct ae_desc ae_desc_list[] = { {IRDMA_AE_AMP_UNALLOCATED_STAG, "Unallocated memory key (L-Key/R-Key)"}, {IRDMA_AE_AMP_INVALID_STAG, "Invalid memory key (L-Key/R-Key)"}, @@ -206,7 +207,7 @@ irdma_get_ae_desc(u16 ae_id) * @rf: RDMA PCI function * @ip_addr: ip address for device * @mac_addr: mac address ptr - * @action: modify, delete or add + * @action: modify, delete or add/update */ int irdma_arp_table(struct irdma_pci_f *rf, u32 *ip_addr, const u8 *mac_addr, @@ -220,22 +221,22 @@ irdma_arp_table(struct irdma_pci_f *rf, u32 *ip_addr, const u8 *mac_addr, spin_lock_irqsave(&rf->arp_lock, flags); for (arp_index = 0; (u32)arp_index < rf->arp_table_size; arp_index++) { - if (!memcmp(rf->arp_table[arp_index].ip_addr, ip, sizeof(ip))) + if (!memcmp(rf->arp_table[arp_index].ip_addr, ip, sizeof(ip)) && + !rf->arp_table[arp_index].delete_pending) break; } switch (action) { - case IRDMA_ARP_ADD: - if (arp_index != rf->arp_table_size) { - arp_index = -1; - break; - } - - arp_index = 0; - if (irdma_alloc_rsrc(rf, rf->allocated_arps, rf->arp_table_size, - (u32 *)&arp_index, &rf->next_arp_index)) { - arp_index = -1; - break; + case IRDMA_ARP_ADD_UPDATE: /* ARP Add or Update */ + if (arp_index == rf->arp_table_size) { + if (irdma_alloc_rsrc(rf, rf->allocated_arps, + rf->arp_table_size, + (u32 *)&arp_index, + &rf->next_arp_index)) { + arp_index = -1; + break; + } + atomic_set(&rf->arp_table[arp_index].refcnt, 0); } memcpy(rf->arp_table[arp_index].ip_addr, ip, @@ -252,10 +253,16 @@ irdma_arp_table(struct irdma_pci_f *rf, u32 *ip_addr, const u8 *mac_addr, break; } - memset(rf->arp_table[arp_index].ip_addr, 0, - sizeof(rf->arp_table[arp_index].ip_addr)); - eth_zero_addr(rf->arp_table[arp_index].mac_addr); - irdma_free_rsrc(rf, rf->allocated_arps, arp_index); + if (!atomic_read(&rf->arp_table[arp_index].refcnt)) { + memset(rf->arp_table[arp_index].ip_addr, 0, + sizeof(rf->arp_table[arp_index].ip_addr)); + eth_zero_addr(rf->arp_table[arp_index].mac_addr); + irdma_free_rsrc(rf, rf->allocated_arps, arp_index); + rf->arp_table[arp_index].delete_pending = false; + } else { + rf->arp_table[arp_index].delete_pending = true; + arp_index = -1; /* prevent immediate CQP ARP index deletion */ + } break; default: arp_index = -1; @@ -266,8 +273,61 @@ irdma_arp_table(struct irdma_pci_f *rf, u32 *ip_addr, const u8 *mac_addr, return arp_index; } +static int +irdma_get_arp(struct irdma_pci_f *rf, u16 arp_index) +{ + unsigned long flags; + u32 ip_zero[4] = {}; + + if (arp_index >= rf->arp_table_size) + return -EINVAL; + + spin_lock_irqsave(&rf->arp_lock, flags); + if (!memcmp(rf->arp_table[arp_index].ip_addr, ip_zero, sizeof(ip_zero))) { + spin_unlock_irqrestore(&rf->arp_lock, flags); + return -EINVAL; + } + if (!atomic_read(&rf->arp_table[arp_index].refcnt)) + atomic_set(&rf->arp_table[arp_index].refcnt, 1); + else + atomic_inc(&rf->arp_table[arp_index].refcnt); + spin_unlock_irqrestore(&rf->arp_lock, flags); + + return 0; +} + +static void +irdma_put_arp(struct irdma_pci_f *rf, u16 arp_index) +{ + unsigned long flags; + + if (arp_index >= rf->arp_table_size) + return; + spin_lock_irqsave(&rf->arp_lock, flags); + if (!atomic_dec_and_test(&rf->arp_table[arp_index].refcnt)) { + spin_unlock_irqrestore(&rf->arp_lock, flags); + return; + } + + if (rf->arp_table[arp_index].delete_pending) { + u32 ip_addr[4]; + + memcpy(ip_addr, rf->arp_table[arp_index].ip_addr, + sizeof(ip_addr)); + memset(rf->arp_table[arp_index].ip_addr, 0, + sizeof(rf->arp_table[arp_index].ip_addr)); + eth_zero_addr(rf->arp_table[arp_index].mac_addr); + spin_unlock_irqrestore(&rf->arp_lock, flags); + irdma_arp_cqp_op(rf, arp_index, NULL, IRDMA_ARP_DELETE); + rf->arp_table[arp_index].delete_pending = false; + irdma_free_rsrc(rf, rf->allocated_arps, arp_index); + } else { + spin_unlock_irqrestore(&rf->arp_lock, flags); + } +} + /** - * irdma_add_arp - add a new arp entry if needed + * irdma_add_arp - add a new arp entry if needed and resolve it * @rf: RDMA function * @ip: IP address * @mac: MAC address @@ -275,18 +335,7 @@ irdma_arp_table(struct irdma_pci_f *rf, u32 *ip_addr, const u8 *mac_addr, int irdma_add_arp(struct irdma_pci_f *rf, u32 *ip, const u8 *mac) { - int arpidx; - - arpidx = irdma_arp_table(rf, &ip[0], NULL, IRDMA_ARP_RESOLVE); - if (arpidx >= 0) { - if (ether_addr_equal(rf->arp_table[arpidx].mac_addr, mac)) - return arpidx; - - irdma_manage_arp_cache(rf, rf->arp_table[arpidx].mac_addr, ip, - IRDMA_ARP_DELETE); - } - - irdma_manage_arp_cache(rf, mac, ip, IRDMA_ARP_ADD); + irdma_manage_arp_cache(rf, mac, ip, IRDMA_ARP_ADD_UPDATE); return irdma_arp_table(rf, ip, NULL, IRDMA_ARP_RESOLVE); } @@ -378,6 +427,8 @@ irdma_alloc_and_get_cqp_request(struct irdma_cqp *cqp, atomic_set(&cqp_request->refcnt, 1); memset(&cqp_request->compl_info, 0, sizeof(cqp_request->compl_info)); + memset(&cqp_request->info, 0, sizeof(cqp_request->info)); + return cqp_request; } @@ -503,6 +554,17 @@ irdma_wait_event(struct irdma_pci_f *rf, READ_ONCE(cqp_request->request_done), msecs_to_jiffies(wait_time_ms))) break; + if (cqp_request->info.cqp_cmd_exec_status) { + irdma_debug(&rf->sc_dev, IRDMA_DEBUG_CQP, + "%s (%d) cqp op error status reported: %d, %d %x %x\n", + irdma_cqp_cmd_names[cqp_request->info.cqp_cmd], + cqp_request->info.cqp_cmd, + cqp_request->info.cqp_cmd_exec_status, + cqp_request->compl_info.error, + cqp_request->compl_info.maj_err_code, + cqp_request->compl_info.min_err_code); + break; + } irdma_check_cqp_progress(&cqp_timeout, &rf->sc_dev); @@ -540,7 +602,7 @@ static const char *const irdma_cqp_cmd_names[IRDMA_MAX_CQP_OPS] = { [IRDMA_OP_DELETE_ARP_CACHE_ENTRY] = "Delete ARP Cache Cmd", [IRDMA_OP_MANAGE_APBVT_ENTRY] = "Manage APBV Table Entry Cmd", [IRDMA_OP_CEQ_CREATE] = "CEQ Create Cmd", - [IRDMA_OP_AEQ_CREATE] = "AEQ Destroy Cmd", + [IRDMA_OP_AEQ_CREATE] = "AEQ Create Cmd", [IRDMA_OP_MANAGE_QHASH_TABLE_ENTRY] = "Manage Quad Hash Table Entry Cmd", [IRDMA_OP_QP_MODIFY] = "Modify QP Cmd", [IRDMA_OP_QP_UPLOAD_CONTEXT] = "Upload Context Cmd", @@ -635,7 +697,7 @@ irdma_handle_cqp_op(struct irdma_pci_f *rf, bool put_cqp_request = true; if (rf->reset) - return 0; + return (info->create ? -EBUSY : 0); irdma_get_cqp_request(cqp_request); status = irdma_process_cqp_cmd(dev, info); @@ -654,13 +716,23 @@ irdma_handle_cqp_op(struct irdma_pci_f *rf, err: if (irdma_cqp_crit_err(dev, info->cqp_cmd, cqp_request->compl_info.maj_err_code, - cqp_request->compl_info.min_err_code)) + cqp_request->compl_info.min_err_code)) { + int qpn = -1; + + if (info->cqp_cmd == IRDMA_OP_QP_CREATE) + qpn = cqp_request->info.in.u.qp_create.qp->qp_uk.qp_id; + else if (info->cqp_cmd == IRDMA_OP_QP_MODIFY) + qpn = cqp_request->info.in.u.qp_modify.qp->qp_uk.qp_id; + else if (info->cqp_cmd == IRDMA_OP_QP_DESTROY) + qpn = cqp_request->info.in.u.qp_destroy.qp->qp_uk.qp_id; + irdma_dev_err(&rf->iwdev->ibdev, - "[%s Error][op_code=%d] status=%d waiting=%d completion_err=%d maj=0x%x min=0x%x\n", - irdma_cqp_cmd_names[info->cqp_cmd], info->cqp_cmd, status, + "[%s Error] status=%d waiting=%d completion_err=%d maj=0x%x min=0x%x qpn=%d\n", + irdma_cqp_cmd_names[info->cqp_cmd], status, cqp_request->waiting, cqp_request->compl_info.error, cqp_request->compl_info.maj_err_code, - cqp_request->compl_info.min_err_code); + cqp_request->compl_info.min_err_code, qpn); + } if (put_cqp_request) irdma_put_cqp_request(&rf->cqp, cqp_request); @@ -715,7 +787,7 @@ irdma_cq_rem_ref(struct ib_cq *ibcq) return; } - rf->cq_table[iwcq->cq_num] = NULL; + WRITE_ONCE(rf->cq_table[iwcq->cq_num], NULL); spin_unlock_irqrestore(&rf->cqtable_lock, flags); complete(&iwcq->free_cq); } @@ -1009,6 +1081,7 @@ irdma_cqp_cq_create_cmd(struct irdma_sc_dev *dev, struct irdma_sc_cq *cq) cqp_info->post_sq = 1; cqp_info->in.u.cq_create.cq = cq; cqp_info->in.u.cq_create.scratch = (uintptr_t)cqp_request; + cqp_info->create = true; status = irdma_handle_cqp_op(rf, cqp_request); irdma_put_cqp_request(iwcqp, cqp_request); @@ -1037,13 +1110,13 @@ irdma_cqp_qp_create_cmd(struct irdma_sc_dev *dev, struct irdma_sc_qp *qp) cqp_info = &cqp_request->info; qp_info = &cqp_request->info.in.u.qp_create.info; - memset(qp_info, 0, sizeof(*qp_info)); qp_info->cq_num_valid = true; qp_info->next_iwarp_state = IRDMA_QP_STATE_RTS; cqp_info->cqp_cmd = IRDMA_OP_QP_CREATE; cqp_info->post_sq = 1; cqp_info->in.u.qp_create.qp = qp; cqp_info->in.u.qp_create.scratch = (uintptr_t)cqp_request; + cqp_info->create = true; status = irdma_handle_cqp_op(rf, cqp_request); irdma_put_cqp_request(iwcqp, cqp_request); @@ -1060,10 +1133,10 @@ void irdma_dealloc_push_page(struct irdma_pci_f *rf, struct irdma_qp *iwqp) { + struct irdma_sc_qp *qp = &iwqp->sc_qp; struct irdma_cqp_request *cqp_request; struct cqp_cmds_info *cqp_info; int status; - struct irdma_sc_qp *qp = &iwqp->sc_qp; if (qp->push_idx == IRDMA_INVALID_PUSH_PAGE_INDEX) return; @@ -1081,6 +1154,7 @@ irdma_dealloc_push_page(struct irdma_pci_f *rf, cqp_info->in.u.manage_push_page.info.push_page_type = 0; cqp_info->in.u.manage_push_page.cqp = &rf->cqp.sc_cqp; cqp_info->in.u.manage_push_page.scratch = (uintptr_t)cqp_request; + status = irdma_handle_cqp_op(rf, cqp_request); if (!status) qp->push_idx = IRDMA_INVALID_PUSH_PAGE_INDEX; @@ -1160,6 +1234,7 @@ irdma_hw_modify_qp(struct irdma_device *iwdev, struct irdma_qp *iwqp, cqp_info->post_sq = 1; cqp_info->in.u.qp_modify.qp = &iwqp->sc_qp; cqp_info->in.u.qp_modify.scratch = (uintptr_t)cqp_request; + cqp_info->create = false; status = irdma_handle_cqp_op(rf, cqp_request); irdma_put_cqp_request(&rf->cqp, cqp_request); if (status) { @@ -1241,7 +1316,6 @@ irdma_cqp_qp_destroy_cmd(struct irdma_sc_dev *dev, struct irdma_sc_qp *qp) return -ENOMEM; cqp_info = &cqp_request->info; - memset(cqp_info, 0, sizeof(*cqp_info)); cqp_info->cqp_cmd = IRDMA_OP_QP_DESTROY; cqp_info->post_sq = 1; cqp_info->in.u.qp_destroy.qp = qp; @@ -1306,7 +1380,7 @@ irdma_ieq_get_qp(struct irdma_sc_dev *dev, return NULL; iwqp = cm_node->iwqp; - irdma_rem_ref_cm_node(cm_node); + irdma_rem_ref_cmnode(cm_node); return &iwqp->sc_qp; } @@ -1598,7 +1672,6 @@ irdma_cqp_gather_stats_cmd(struct irdma_sc_dev *dev, return -ENOMEM; cqp_info = &cqp_request->info; - memset(cqp_info, 0, sizeof(*cqp_info)); cqp_info->cqp_cmd = IRDMA_OP_STATS_GATHER; cqp_info->post_sq = 1; cqp_info->in.u.stats_gather.info = pestat->gather_info; @@ -1616,44 +1689,6 @@ irdma_cqp_gather_stats_cmd(struct irdma_sc_dev *dev, } /** - * irdma_cqp_stats_inst_cmd - Allocate/free stats instance - * @vsi: pointer to vsi structure - * @cmd: command to allocate or free - * @stats_info: pointer to allocate stats info - */ -int -irdma_cqp_stats_inst_cmd(struct irdma_sc_vsi *vsi, u8 cmd, - struct irdma_stats_inst_info *stats_info) -{ - struct irdma_pci_f *rf = dev_to_rf(vsi->dev); - struct irdma_cqp *iwcqp = &rf->cqp; - struct irdma_cqp_request *cqp_request; - struct cqp_cmds_info *cqp_info; - int status; - bool wait = false; - - if (cmd == IRDMA_OP_STATS_ALLOCATE) - wait = true; - cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, wait); - if (!cqp_request) - return -ENOMEM; - - cqp_info = &cqp_request->info; - memset(cqp_info, 0, sizeof(*cqp_info)); - cqp_info->cqp_cmd = cmd; - cqp_info->post_sq = 1; - cqp_info->in.u.stats_manage.info = *stats_info; - cqp_info->in.u.stats_manage.scratch = (uintptr_t)cqp_request; - cqp_info->in.u.stats_manage.cqp = &rf->cqp.sc_cqp; - status = irdma_handle_cqp_op(rf, cqp_request); - if (wait) - stats_info->stats_idx = cqp_request->compl_info.op_ret_val; - irdma_put_cqp_request(iwcqp, cqp_request); - - return status; -} - -/** * irdma_cqp_ceq_cmd - Create/Destroy CEQ's after CEQ 0 * @dev: pointer to device info * @sc_ceq: pointer to ceq structure @@ -1743,12 +1778,12 @@ irdma_cqp_ws_node_cmd(struct irdma_sc_dev *dev, u8 cmd, return -ENOMEM; cqp_info = &cqp_request->info; - memset(cqp_info, 0, sizeof(*cqp_info)); cqp_info->cqp_cmd = cmd; cqp_info->post_sq = 1; cqp_info->in.u.ws_node.info = *node_info; cqp_info->in.u.ws_node.cqp = cqp; cqp_info->in.u.ws_node.scratch = (uintptr_t)cqp_request; + cqp_info->create = true; status = irdma_handle_cqp_op(rf, cqp_request); if (status) goto exit; @@ -1773,7 +1808,7 @@ exit: } /** - * irdma_ah_cqp_op - perform an AH cqp operation + * irdma_ah_do_cqp - perform an AH cqp operation * @rf: RDMA PCI function * @sc_ah: address handle * @cmd: AH operation @@ -1783,8 +1818,8 @@ exit: * * returns errno */ -int -irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd, +static int +irdma_ah_do_cqp(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd, bool wait, void (*callback_fcn) (struct irdma_cqp_request *), void *cb_param) @@ -1811,6 +1846,7 @@ irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd, cqp_info->in.u.ah_create.info = sc_ah->ah_info; cqp_info->in.u.ah_create.scratch = (uintptr_t)cqp_request; cqp_info->in.u.ah_create.cqp = &rf->cqp.sc_cqp; + cqp_info->create = true; } else if (cmd == IRDMA_OP_AH_DESTROY) { cqp_info->in.u.ah_destroy.info = sc_ah->ah_info; cqp_info->in.u.ah_destroy.scratch = (uintptr_t)cqp_request; @@ -1833,6 +1869,36 @@ irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd, return 0; } +int +irdma_ah_cqp_op(struct irdma_pci_f *rf, struct irdma_sc_ah *sc_ah, u8 cmd, + bool wait, + void (*callback_fcn) (struct irdma_cqp_request *), + void *cb_param) +{ + int status; + + if (cmd == IRDMA_OP_AH_CREATE) { + status = irdma_get_arp(rf, sc_ah->ah_info.dst_arpindex); + if (status) { + irdma_dev_err(&rf->iwdev->ibdev, "%s get_arp failed for index = %d\n", + __func__, sc_ah->ah_info.dst_arpindex); + + return -EINVAL; + } + status = irdma_ah_do_cqp(rf, sc_ah, cmd, wait, callback_fcn, + cb_param); + if (status) + irdma_put_arp(rf, sc_ah->ah_info.dst_arpindex); + } else { + status = irdma_ah_do_cqp(rf, sc_ah, cmd, wait, callback_fcn, + cb_param); + if (cmd == IRDMA_OP_AH_DESTROY) + irdma_put_arp(rf, sc_ah->ah_info.dst_arpindex); + } + + return status; +} + /** * irdma_ieq_ah_cb - callback after creation of AH for IEQ * @cqp_request: pointer to cqp_request of create AH @@ -1853,6 +1919,9 @@ irdma_ieq_ah_cb(struct irdma_cqp_request *cqp_request) irdma_ieq_cleanup_qp(qp->vsi->ieq, qp); } spin_unlock_irqrestore(&qp->pfpdu.lock, flags); + if (!cqp_request->waiting) + irdma_put_cqp_request(sc_ah->dev->cqp->back_cqp, + cqp_request); } /** @@ -1867,6 +1936,9 @@ irdma_ilq_ah_cb(struct irdma_cqp_request *cqp_request) sc_ah->ah_info.ah_valid = !cqp_request->compl_info.op_ret_val; irdma_add_conn_est_qh(cm_node); + if (!cqp_request->waiting) + irdma_put_cqp_request(sc_ah->dev->cqp->back_cqp, + cqp_request); } /** @@ -2239,39 +2311,35 @@ clear_qp_ctx_addr(__le64 * ctx) /** * irdma_upload_qp_context - upload raw QP context - * @iwqp: QP pointer + * @rf: RDMA PCI function + * @qpn: QP ID + * @qp_type: QP Type * @freeze: freeze QP * @raw: raw context flag */ int -irdma_upload_qp_context(struct irdma_qp *iwqp, bool freeze, bool raw) +irdma_upload_qp_context(struct irdma_pci_f *rf, u32 qpn, + u8 qp_type, bool freeze, bool raw) { struct irdma_dma_mem dma_mem; struct irdma_sc_dev *dev; - struct irdma_sc_qp *qp; struct irdma_cqp *iwcqp; struct irdma_cqp_request *cqp_request; struct cqp_cmds_info *cqp_info; struct irdma_upload_context_info *info; - struct irdma_pci_f *rf; int ret; u32 *ctx; - rf = iwqp->iwdev->rf; - if (!rf) - return -EINVAL; - - qp = &iwqp->sc_qp; dev = &rf->sc_dev; iwcqp = &rf->cqp; cqp_request = irdma_alloc_and_get_cqp_request(iwcqp, true); - if (!cqp_request) + if (!cqp_request) { + irdma_debug((dev), IRDMA_DEBUG_QP, "Could not get CQP req for QP [%u]\n", qpn); return -EINVAL; - + } cqp_info = &cqp_request->info; info = &cqp_info->in.u.qp_upload_context.info; - memset(info, 0, sizeof(struct irdma_upload_context_info)); cqp_info->cqp_cmd = IRDMA_OP_QP_UPLOAD_CONTEXT; cqp_info->post_sq = 1; cqp_info->in.u.qp_upload_context.dev = dev; @@ -2281,6 +2349,7 @@ irdma_upload_qp_context(struct irdma_qp *iwqp, bool freeze, bool raw) dma_mem.va = irdma_allocate_dma_mem(dev->hw, &dma_mem, dma_mem.size, PAGE_SIZE); if (!dma_mem.va) { irdma_put_cqp_request(&rf->cqp, cqp_request); + irdma_debug((dev), IRDMA_DEBUG_QP, "Could not allocate buffer for QP [%u]\n", qpn); return -ENOMEM; } @@ -2288,20 +2357,21 @@ irdma_upload_qp_context(struct irdma_qp *iwqp, bool freeze, bool raw) info->buf_pa = dma_mem.pa; info->raw_format = raw; info->freeze_qp = freeze; - info->qp_type = qp->qp_uk.qp_type; /* 1 is iWARP and 2 UDA */ - info->qp_id = qp->qp_uk.qp_id; + info->qp_type = qp_type; /* 1 is iWARP and 2 UDA */ + info->qp_id = qpn; ret = irdma_handle_cqp_op(rf, cqp_request); if (ret) goto error; - irdma_debug(dev, IRDMA_DEBUG_QP, "PRINT CONTXT QP [%d]\n", info->qp_id); + irdma_debug((dev), IRDMA_DEBUG_QP, "PRINT CONTXT QP [%u]\n", info->qp_id); { u32 i, j; clear_qp_ctx_addr(dma_mem.va); for (i = 0, j = 0; i < 32; i++, j += 4) - irdma_debug(dev, IRDMA_DEBUG_QP, - "%d:\t [%08X %08x %08X %08X]\n", (j * 4), - ctx[j], ctx[j + 1], ctx[j + 2], ctx[j + 3]); + irdma_debug((dev), IRDMA_DEBUG_QP, + "[%u] %u:\t [%08X %08x %08X %08X]\n", + info->qp_id, (j * 4), ctx[j], ctx[j + 1], + ctx[j + 2], ctx[j + 3]); } error: irdma_put_cqp_request(iwcqp, cqp_request); @@ -2310,20 +2380,41 @@ error: return ret; } -bool -irdma_cq_empty(struct irdma_cq *iwcq) +static bool +qp_has_unpolled_cqes(struct irdma_qp *iwqp, struct irdma_cq *iwcq) { - struct irdma_cq_uk *ukcq; - u64 qword3; + struct irdma_cq_uk *cq = &iwcq->sc_cq.cq_uk; + struct irdma_qp_uk *qp = &iwqp->sc_qp.qp_uk; + u32 cq_head = IRDMA_RING_CURRENT_HEAD(cq->cq_ring); + u64 qword3, comp_ctx; __le64 *cqe; - u8 polarity; + u8 polarity, cq_polarity; + + cq_polarity = cq->polarity; + do { + if (cq->avoid_mem_cflct) + cqe = ((struct irdma_extended_cqe *)(cq->cq_base))[cq_head].buf; + else + cqe = cq->cq_base[cq_head].buf; + get_64bit_val(cqe, IRDMA_BYTE_24, &qword3); + polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword3); + + if (polarity != cq_polarity) + break; + + /* Ensure CQE contents are read after valid bit is checked */ + rmb(); + + get_64bit_val(cqe, IRDMA_BYTE_8, &comp_ctx); + if ((struct irdma_qp_uk *)(irdma_uintptr) comp_ctx == qp) + return true; - ukcq = &iwcq->sc_cq.cq_uk; - cqe = IRDMA_GET_CURRENT_CQ_ELEM(ukcq); - get_64bit_val(cqe, 24, &qword3); - polarity = (u8)FIELD_GET(IRDMA_CQ_VALID, qword3); + cq_head = (cq_head + 1) % cq->cq_ring.size; + if (!cq_head) + cq_polarity ^= 1; + } while (true); - return polarity != ukcq->polarity; + return false; } void @@ -2380,11 +2471,18 @@ irdma_set_cpi_common_values(struct irdma_cq_poll_info *cpi, static inline void irdma_comp_handler(struct irdma_cq *cq) { + struct irdma_device *iwdev = to_iwdev(cq->ibcq.device); + struct irdma_ceq *ceq = &iwdev->rf->ceqlist[cq->sc_cq.ceq_id]; + unsigned long flags; + if (!cq->ibcq.comp_handler) return; - if (atomic_cmpxchg(&cq->armed, 1, 0)) + if (atomic_read(&cq->armed)) { + spin_lock_irqsave(&ceq->ce_lock, flags); cq->ibcq.comp_handler(&cq->ibcq, cq->ibcq.cq_context); + spin_unlock_irqrestore(&ceq->ce_lock, flags); + } } /** @@ -2405,7 +2503,7 @@ irdma_generate_flush_completions(struct irdma_qp *iwqp) unsigned long flags1; spin_lock_irqsave(&iwqp->iwscq->lock, flags1); - if (irdma_cq_empty(iwqp->iwscq)) { + if (!qp_has_unpolled_cqes(iwqp, iwqp->iwscq)) { unsigned long flags2; spin_lock_irqsave(&iwqp->lock, flags2); @@ -2452,7 +2550,7 @@ irdma_generate_flush_completions(struct irdma_qp *iwqp) } spin_lock_irqsave(&iwqp->iwrcq->lock, flags1); - if (irdma_cq_empty(iwqp->iwrcq)) { + if (!qp_has_unpolled_cqes(iwqp, iwqp->iwrcq)) { unsigned long flags2; spin_lock_irqsave(&iwqp->lock, flags2); @@ -2527,3 +2625,49 @@ irdma_udqp_qs_worker(struct work_struct *work) irdma_qp_rem_ref(&udqs_work->iwqp->ibqp); kfree(udqs_work); } + +void +irdma_chk_free_stag(struct irdma_pci_f *rf) +{ + struct irdma_cqp_request *cqp_request; + struct cqp_cmds_info *cqp_info; + struct irdma_dealloc_stag_info *info; + + cqp_request = irdma_alloc_and_get_cqp_request(&rf->cqp, true); + if (!cqp_request) + return; + + cqp_info = &cqp_request->info; + info = &cqp_info->in.u.dealloc_stag.info; + info->stag_idx = RS_64_1(rf->chk_stag, IRDMA_CQPSQ_STAG_IDX_S); + cqp_info->cqp_cmd = IRDMA_OP_DEALLOC_STAG; + cqp_info->post_sq = 1; + cqp_info->in.u.dealloc_stag.dev = &rf->sc_dev; + cqp_info->in.u.dealloc_stag.scratch = (uintptr_t)cqp_request; + irdma_handle_cqp_op(rf, cqp_request); + irdma_put_cqp_request(&rf->cqp, cqp_request); +} + +void +cqp_poll_worker(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct irdma_pci_f *rf = container_of(dwork, struct irdma_pci_f, dwork_cqp_poll); + struct irdma_mr iwmr = {}; + struct irdma_pd *iwpd; + + iwpd = kzalloc(sizeof(*iwpd), GFP_KERNEL); + if (!iwpd) + return; + iwmr.stag = rf->chk_stag; + iwmr.ibmw.type = IB_MW_TYPE_1; + iwmr.ibmr.pd = &iwpd->ibpd; + if (irdma_hw_alloc_mw(rf->iwdev, &iwmr)) + goto exit; + irdma_chk_free_stag(rf); + + mod_delayed_work(rf->iwdev->cleanup_wq, &rf->dwork_cqp_poll, + msecs_to_jiffies(3000)); +exit: + kfree(iwpd); +} diff --git a/sys/dev/irdma/irdma_verbs.c b/sys/dev/irdma/irdma_verbs.c index 59d4bf392562..a131286d1d37 100644 --- a/sys/dev/irdma/irdma_verbs.c +++ b/sys/dev/irdma/irdma_verbs.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2023 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -60,7 +60,6 @@ irdma_query_device(struct ib_device *ibdev, irdma_fw_minor_ver(&rf->sc_dev); props->device_cap_flags = IB_DEVICE_MEM_WINDOW | IB_DEVICE_MEM_MGT_EXTENSIONS; - props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY; props->vendor_id = pcidev->vendor; props->vendor_part_id = pcidev->device; props->hw_ver = pcidev->revision; @@ -229,6 +228,7 @@ irdma_alloc_push_page(struct irdma_qp *iwqp) cqp_info->in.u.manage_push_page.info.push_page_type = 0; cqp_info->in.u.manage_push_page.cqp = &iwdev->rf->cqp.sc_cqp; cqp_info->in.u.manage_push_page.scratch = (uintptr_t)cqp_request; + cqp_info->create = true; status = irdma_handle_cqp_op(iwdev->rf, cqp_request); if (!status && cqp_request->compl_info.op_ret_val < @@ -273,9 +273,20 @@ irdma_clean_cqes(struct irdma_qp *iwqp, struct irdma_cq *iwcq) { struct irdma_cq_uk *ukcq = &iwcq->sc_cq.cq_uk; unsigned long flags; + struct irdma_cmpl_gen *cmpl_node; + struct list_head *tmp_node, *list_node; spin_lock_irqsave(&iwcq->lock, flags); irdma_uk_clean_cq(&iwqp->sc_qp.qp_uk, ukcq); + + list_for_each_safe(list_node, tmp_node, &iwcq->cmpl_generated) { + cmpl_node = list_entry(list_node, struct irdma_cmpl_gen, list); + if (cmpl_node->cpi.qp_id == iwqp->ibqp.qp_num) { + list_del(&cmpl_node->list); + kfree(cmpl_node); + } + } + spin_unlock_irqrestore(&iwcq->lock, flags); } @@ -390,8 +401,7 @@ irdma_setup_umode_qp(struct ib_udata *udata, ret = ib_copy_from_udata(&req, udata, min(sizeof(req), udata->inlen)); if (ret) { - irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_VERBS, - "ib_copy_from_data fail\n"); + irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_VERBS, "ib_copy_from_data fail\n"); return ret; } @@ -406,8 +416,7 @@ irdma_setup_umode_qp(struct ib_udata *udata, if (!iwqp->iwpbl) { ret = -ENODATA; - irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_VERBS, - "no pbl info\n"); + irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_VERBS, "no pbl info\n"); return ret; } } @@ -524,7 +533,6 @@ irdma_setup_kmode_qp(struct irdma_device *iwdev, info->shadow_area_pa = info->rq_pa + (ukinfo->rq_depth * IRDMA_QP_WQE_MIN_SIZE); ukinfo->sq_size = ukinfo->sq_depth >> ukinfo->sq_shift; ukinfo->rq_size = ukinfo->rq_depth >> ukinfo->rq_shift; - ukinfo->qp_id = iwqp->ibqp.qp_num; iwqp->max_send_wr = (ukinfo->sq_depth - IRDMA_SQ_RSVD) >> ukinfo->sq_shift; iwqp->max_recv_wr = (ukinfo->rq_depth - IRDMA_RQ_RSVD) >> ukinfo->rq_shift; @@ -549,7 +557,6 @@ irdma_cqp_create_qp_cmd(struct irdma_qp *iwqp) cqp_info = &cqp_request->info; qp_info = &cqp_request->info.in.u.qp_create.info; - memset(qp_info, 0, sizeof(*qp_info)); qp_info->mac_valid = true; qp_info->cq_num_valid = true; qp_info->next_iwarp_state = IRDMA_QP_STATE_IDLE; @@ -558,6 +565,7 @@ irdma_cqp_create_qp_cmd(struct irdma_qp *iwqp) cqp_info->post_sq = 1; cqp_info->in.u.qp_create.qp = &iwqp->sc_qp; cqp_info->in.u.qp_create.scratch = (uintptr_t)cqp_request; + cqp_info->create = true; status = irdma_handle_cqp_op(rf, cqp_request); irdma_put_cqp_request(&rf->cqp, cqp_request); @@ -574,7 +582,7 @@ irdma_roce_fill_and_set_qpctx_info(struct irdma_qp *iwqp, struct irdma_udp_offload_info *udp_info; udp_info = &iwqp->udp_info; - udp_info->snd_mss = ib_mtu_enum_to_int(ib_mtu_int_to_enum(iwdev->vsi.mtu)); + udp_info->snd_mss = ib_mtu_enum_to_int(iboe_get_mtu(iwdev->vsi.mtu)); udp_info->cwnd = iwdev->roce_cwnd; udp_info->rexmit_thresh = 2; udp_info->rnr_nak_thresh = 2; @@ -680,7 +688,26 @@ irdma_sched_qp_flush_work(struct irdma_qp *iwqp) } void -irdma_flush_worker(struct work_struct *work) +irdma_user_flush_worker(struct work_struct *work) +{ + struct delayed_work *dwork = to_delayed_work(work); + struct irdma_qp *iwqp = container_of(dwork, struct irdma_qp, + dwork_flush); + + /* + * Set the WAIT flag to prevent a massive buildup of flush commands in the extreme case of many QPs lingering + * in the ERROR state. + */ + irdma_flush_wqes(iwqp, IRDMA_FLUSH_SQ | IRDMA_FLUSH_RQ | IRDMA_REFLUSH | + IRDMA_FLUSH_WAIT); + + /* Re-arm continuously. Work is canceled when QP is deleted. */ + mod_delayed_work(iwqp->iwdev->cleanup_wq, &iwqp->dwork_flush, + msecs_to_jiffies(IRDMA_PERIODIC_FLUSH_MS)); +} + +void +irdma_kern_flush_worker(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); struct irdma_qp *iwqp = container_of(dwork, struct irdma_qp, dwork_flush); @@ -974,8 +1001,7 @@ irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, if (attr_mask & IB_QP_STATE) { if (!ib_modify_qp_is_ok(iwqp->ibqp_state, attr->qp_state, iwqp->ibqp.qp_type, attr_mask)) { - irdma_dev_warn(&iwdev->ibdev, - "modify_qp invalid for qp_id=%d, old_state=0x%x, new_state=0x%x\n", + irdma_dev_warn(&iwdev->ibdev, "modify_qp invalid for qp_id=%d, old_state=0x%x, new_state=0x%x\n", iwqp->ibqp.qp_num, iwqp->ibqp_state, attr->qp_state); ret = -EINVAL; @@ -1022,8 +1048,7 @@ irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, udp_info->cwnd = iwdev->roce_cwnd; roce_info->ack_credits = iwdev->roce_ackcreds; if (iwdev->push_mode && udata && - iwqp->sc_qp.push_idx == IRDMA_INVALID_PUSH_PAGE_INDEX && - dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) { + iwqp->sc_qp.push_idx == IRDMA_INVALID_PUSH_PAGE_INDEX) { spin_unlock_irqrestore(&iwqp->lock, flags); irdma_alloc_push_page(iwqp); spin_lock_irqsave(&iwqp->lock, flags); @@ -1090,14 +1115,14 @@ irdma_modify_qp_roce(struct ib_qp *ibqp, struct ib_qp_attr *attr, if (iwqp->iwarp_state == info.curr_iwarp_state) { iwqp->iwarp_state = info.next_iwarp_state; iwqp->ibqp_state = attr->qp_state; + iwqp->sc_qp.qp_state = iwqp->iwarp_state; } if (iwqp->ibqp_state > IB_QPS_RTS && - !iwqp->flush_issued) { + !atomic_read(&iwqp->flush_issued)) { spin_unlock_irqrestore(&iwqp->lock, flags); irdma_flush_wqes(iwqp, IRDMA_FLUSH_SQ | IRDMA_FLUSH_RQ | IRDMA_FLUSH_WAIT); - iwqp->flush_issued = 1; } else { spin_unlock_irqrestore(&iwqp->lock, flags); @@ -1198,8 +1223,7 @@ irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, issue_modify_qp = 1; } if (iwdev->push_mode && udata && - iwqp->sc_qp.push_idx == IRDMA_INVALID_PUSH_PAGE_INDEX && - dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) { + iwqp->sc_qp.push_idx == IRDMA_INVALID_PUSH_PAGE_INDEX) { spin_unlock_irqrestore(&iwqp->lock, flags); irdma_alloc_push_page(iwqp); spin_lock_irqsave(&iwqp->lock, flags); @@ -1318,6 +1342,7 @@ irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, if (iwqp->iwarp_state == info.curr_iwarp_state) { iwqp->iwarp_state = info.next_iwarp_state; iwqp->ibqp_state = attr->qp_state; + iwqp->sc_qp.qp_state = iwqp->iwarp_state; } spin_unlock_irqrestore(&iwqp->lock, flags); } @@ -1337,7 +1362,7 @@ irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, spin_lock_irqsave(&iwdev->cm_core.ht_lock, flags); if (iwqp->cm_node) { - atomic_inc(&iwqp->cm_node->refcnt); + irdma_add_ref_cmnode(iwqp->cm_node); spin_unlock_irqrestore(&iwdev->cm_core.ht_lock, flags); close_timer_started = atomic_inc_return(&iwqp->close_timer_started); if (iwqp->cm_id && close_timer_started == 1) @@ -1345,7 +1370,7 @@ irdma_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, (struct irdma_puda_buf *)iwqp, IRDMA_TIMER_TYPE_CLOSE, 1, 0); - irdma_rem_ref_cm_node(iwqp->cm_node); + irdma_rem_ref_cmnode(iwqp->cm_node); } else { spin_unlock_irqrestore(&iwdev->cm_core.ht_lock, flags); } @@ -1482,11 +1507,11 @@ irdma_resize_cq(struct ib_cq *ibcq, int entries, if (!iwcq->user_mode) { entries++; - if (rf->sc_dev.hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2) + if (dev->hw_attrs.uk_attrs.hw_rev == IRDMA_GEN_2) entries *= 2; } - info.cq_size = max(entries, 4); + info.cq_size = max_t(int, entries, 4); if (info.cq_size == iwcq->sc_cq.cq_uk.cq_size - 1) return 0; @@ -1557,6 +1582,7 @@ irdma_resize_cq(struct ib_cq *ibcq, int entries, cqp_info->in.u.cq_modify.cq = &iwcq->sc_cq; cqp_info->in.u.cq_modify.scratch = (uintptr_t)cqp_request; cqp_info->post_sq = 1; + cqp_info->create = true; ret = irdma_handle_cqp_op(rf, cqp_request); irdma_put_cqp_request(&rf->cqp, cqp_request); if (ret) @@ -1668,7 +1694,7 @@ irdma_check_mem_contiguous(u64 *arr, u32 npages, u32 pg_size) u32 pg_idx; for (pg_idx = 0; pg_idx < npages; pg_idx++) { - if ((*arr + (pg_size * pg_idx)) != arr[pg_idx]) + if ((*arr + ((u64)pg_size * pg_idx)) != arr[pg_idx]) return false; } @@ -1835,6 +1861,44 @@ irdma_handle_q_mem(struct irdma_device *iwdev, } /** + * irdma_hw_alloc_mw - create the hw memory window + * @iwdev: irdma device + * @iwmr: pointer to memory window info + */ +int +irdma_hw_alloc_mw(struct irdma_device *iwdev, struct irdma_mr *iwmr) +{ + struct irdma_mw_alloc_info *info; + struct irdma_pd *iwpd = to_iwpd(iwmr->ibmr.pd); + struct irdma_cqp_request *cqp_request; + struct cqp_cmds_info *cqp_info; + int status; + + cqp_request = irdma_alloc_and_get_cqp_request(&iwdev->rf->cqp, true); + if (!cqp_request) + return -ENOMEM; + + cqp_info = &cqp_request->info; + info = &cqp_info->in.u.mw_alloc.info; + if (iwmr->ibmw.type == IB_MW_TYPE_1) + info->mw_wide = true; + + info->page_size = PAGE_SIZE; + info->mw_stag_index = iwmr->stag >> IRDMA_CQPSQ_STAG_IDX_S; + info->pd_id = iwpd->sc_pd.pd_id; + info->remote_access = true; + cqp_info->cqp_cmd = IRDMA_OP_MW_ALLOC; + cqp_info->post_sq = 1; + cqp_info->in.u.mw_alloc.dev = &iwdev->rf->sc_dev; + cqp_info->in.u.mw_alloc.scratch = (uintptr_t)cqp_request; + cqp_info->create = true; + status = irdma_handle_cqp_op(iwdev->rf, cqp_request); + irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request); + + return status; +} + +/** * irdma_hw_alloc_stag - cqp command to allocate stag * @iwdev: irdma device * @iwmr: irdma mr pointer @@ -1856,7 +1920,6 @@ irdma_hw_alloc_stag(struct irdma_device *iwdev, cqp_info = &cqp_request->info; info = &cqp_info->in.u.alloc_stag.info; - memset(info, 0, sizeof(*info)); info->page_size = PAGE_SIZE; info->stag_idx = iwmr->stag >> IRDMA_CQPSQ_STAG_IDX_S; info->pd_id = iwpd->sc_pd.pd_id; @@ -1867,6 +1930,7 @@ irdma_hw_alloc_stag(struct irdma_device *iwdev, cqp_info->post_sq = 1; cqp_info->in.u.alloc_stag.dev = &iwdev->rf->sc_dev; cqp_info->in.u.alloc_stag.scratch = (uintptr_t)cqp_request; + cqp_info->create = true; status = irdma_handle_cqp_op(iwdev->rf, cqp_request); irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request); if (!status) @@ -1948,12 +2012,14 @@ irdma_hwreg_mr(struct irdma_device *iwdev, struct irdma_mr *iwmr, cqp_info = &cqp_request->info; stag_info = &cqp_info->in.u.mr_reg_non_shared.info; - memset(stag_info, 0, sizeof(*stag_info)); stag_info->va = iwpbl->user_base; stag_info->stag_idx = iwmr->stag >> IRDMA_CQPSQ_STAG_IDX_S; stag_info->stag_key = (u8)iwmr->stag; stag_info->total_len = iwmr->len; - stag_info->all_memory = (pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY) ? true : false; + if ((pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY) || iwmr->dma_mr) + stag_info->all_memory = true; + else + stag_info->all_memory = false; stag_info->access_rights = irdma_get_mr_access(access, iwdev->rf->sc_dev.hw_attrs.uk_attrs.hw_rev); stag_info->pd_id = iwpd->sc_pd.pd_id; @@ -1979,6 +2045,7 @@ irdma_hwreg_mr(struct irdma_device *iwdev, struct irdma_mr *iwmr, cqp_info->post_sq = 1; cqp_info->in.u.mr_reg_non_shared.dev = &iwdev->rf->sc_dev; cqp_info->in.u.mr_reg_non_shared.scratch = (uintptr_t)cqp_request; + cqp_info->create = true; ret = irdma_handle_cqp_op(iwdev->rf, cqp_request); irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request); @@ -1992,7 +2059,7 @@ irdma_hwreg_mr(struct irdma_device *iwdev, struct irdma_mr *iwmr, * irdma_alloc_iwmr - Allocate iwmr @region - memory region @pd - protection domain @virt - virtual address @reg_type - * registration type */ -static struct irdma_mr * +struct irdma_mr * irdma_alloc_iwmr(struct ib_umem *region, struct ib_pd *pd, u64 virt, enum irdma_memreg_type reg_type) @@ -2022,19 +2089,17 @@ irdma_alloc_iwmr(struct ib_umem *region, return iwmr; } -static void +void irdma_free_iwmr(struct irdma_mr *iwmr) { kfree(iwmr); } /* - * irdma_reg_user_mr_type_mem - Handle memory registration - * @iwmr - irdma mr - * @access - access rights - * @create_stag - flag to create stag or not + * irdma_reg_user_mr_type_mem - Handle memory registration @iwmr - irdma mr @access - access rights @create_stag - flag + * to create stag or not */ -static int +int irdma_reg_user_mr_type_mem(struct irdma_mr *iwmr, int access, bool create_stag) { @@ -2091,7 +2156,7 @@ free_pble: /* * irdma_reg_user_mr_type_qp - Handle QP memory registration @req - memory reg req @udata - user info @iwmr - irdma mr */ -static int +int irdma_reg_user_mr_type_qp(struct irdma_mem_reg_req req, struct ib_udata *udata, struct irdma_mr *iwmr) @@ -2104,6 +2169,11 @@ irdma_reg_user_mr_type_qp(struct irdma_mem_reg_req req, int err; u8 lvl; + /* iWarp: Catch page not starting on OS page boundary */ + if (!rdma_protocol_roce(&iwdev->ibdev, 1) && + ib_umem_offset(iwmr->region)) + return -EINVAL; + total = req.sq_pages + req.rq_pages + IRDMA_SHADOW_PGCNT; if (total > iwmr->page_cnt) return -EINVAL; @@ -2126,7 +2196,7 @@ irdma_reg_user_mr_type_qp(struct irdma_mem_reg_req req, /* * irdma_reg_user_mr_type_cq - Handle CQ memory registration @req - memory reg req @udata - user info @iwmr - irdma mr */ -static int +int irdma_reg_user_mr_type_cq(struct irdma_mem_reg_req req, struct ib_udata *udata, struct irdma_mr *iwmr) @@ -2158,85 +2228,6 @@ irdma_reg_user_mr_type_cq(struct irdma_mem_reg_req req, return 0; } -/** - * irdma_reg_user_mr - Register a user memory region - * @pd: ptr of pd - * @start: virtual start address - * @len: length of mr - * @virt: virtual address - * @access: access of mr - * @udata: user data - */ -static struct ib_mr * -irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len, - u64 virt, int access, - struct ib_udata *udata) -{ -#define IRDMA_MEM_REG_MIN_REQ_LEN offsetofend(struct irdma_mem_reg_req, sq_pages) - struct irdma_device *iwdev = to_iwdev(pd->device); - struct irdma_mem_reg_req req = {}; - struct ib_umem *region; - struct irdma_mr *iwmr; - int err; - - if (len > iwdev->rf->sc_dev.hw_attrs.max_mr_size) - return ERR_PTR(-EINVAL); - - if (udata->inlen < IRDMA_MEM_REG_MIN_REQ_LEN) - return ERR_PTR(-EINVAL); - - region = ib_umem_get(pd->uobject->context, start, len, access, 0); - - if (IS_ERR(region)) { - irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_VERBS, - "Failed to create ib_umem region\n"); - return (struct ib_mr *)region; - } - - if (ib_copy_from_udata(&req, udata, min(sizeof(req), udata->inlen))) { - ib_umem_release(region); - return ERR_PTR(-EFAULT); - } - - iwmr = irdma_alloc_iwmr(region, pd, virt, req.reg_type); - if (IS_ERR(iwmr)) { - ib_umem_release(region); - return (struct ib_mr *)iwmr; - } - - switch (req.reg_type) { - case IRDMA_MEMREG_TYPE_QP: - err = irdma_reg_user_mr_type_qp(req, udata, iwmr); - if (err) - goto error; - - break; - case IRDMA_MEMREG_TYPE_CQ: - err = irdma_reg_user_mr_type_cq(req, udata, iwmr); - if (err) - goto error; - - break; - case IRDMA_MEMREG_TYPE_MEM: - err = irdma_reg_user_mr_type_mem(iwmr, access, true); - if (err) - goto error; - - break; - default: - err = -EINVAL; - goto error; - } - - return &iwmr->ibmr; - -error: - ib_umem_release(region); - irdma_free_iwmr(iwmr); - - return ERR_PTR(err); -} - int irdma_hwdereg_mr(struct ib_mr *ib_mr) { @@ -2262,10 +2253,11 @@ irdma_hwdereg_mr(struct ib_mr *ib_mr) cqp_info = &cqp_request->info; info = &cqp_info->in.u.dealloc_stag.info; - memset(info, 0, sizeof(*info)); info->pd_id = iwpd->sc_pd.pd_id; info->stag_idx = RS_64_1(ib_mr->rkey, IRDMA_CQPSQ_STAG_IDX_S); info->mr = true; + if (iwmr->type != IRDMA_MEMREG_TYPE_MEM) + info->skip_flush_markers = true; if (iwpbl->pbl_allocated) info->dealloc_pbl = true; @@ -2303,7 +2295,8 @@ irdma_rereg_mr_trans(struct irdma_mr *iwmr, u64 start, u64 len, if (IS_ERR(region)) { irdma_debug(&iwdev->rf->sc_dev, IRDMA_DEBUG_VERBS, - "Failed to create ib_umem region\n"); + "Failed to create ib_umem region err=%ld\n", + PTR_ERR(region)); return (struct ib_mr *)region; } @@ -2335,10 +2328,11 @@ err: * @size: size of memory to register * @access: Access rights * @iova_start: start of virtual address for physical buffers + * @dma_mr: Flag indicating DMA Mem region */ struct ib_mr * irdma_reg_phys_mr(struct ib_pd *pd, u64 addr, u64 size, int access, - u64 *iova_start) + u64 *iova_start, bool dma_mr) { struct irdma_device *iwdev = to_iwdev(pd->device); struct irdma_pbl *iwpbl; @@ -2355,6 +2349,7 @@ irdma_reg_phys_mr(struct ib_pd *pd, u64 addr, u64 size, int access, iwpbl = &iwmr->iwpbl; iwpbl->iwmr = iwmr; iwmr->type = IRDMA_MEMREG_TYPE_MEM; + iwmr->dma_mr = dma_mr; iwpbl->user_base = *iova_start; stag = irdma_create_stag(iwdev); if (!stag) { @@ -2394,7 +2389,7 @@ irdma_get_dma_mr(struct ib_pd *pd, int acc) { u64 kva = 0; - return irdma_reg_phys_mr(pd, 0, 0, acc, &kva); + return irdma_reg_phys_mr(pd, 0, 0, acc, &kva, true); } /** @@ -2547,7 +2542,7 @@ irdma_post_send(struct ib_qp *ibqp, break; case IB_WR_LOCAL_INV: info.op_type = IRDMA_OP_TYPE_INV_STAG; - info.local_fence = info.read_fence; + info.local_fence = true; info.op.inv_local_stag.target_stag = ib_wr->ex.invalidate_rkey; err = irdma_uk_stag_local_invalidate(ukqp, &info, true); break; @@ -2593,7 +2588,7 @@ irdma_post_send(struct ib_qp *ibqp, ib_wr = ib_wr->next; } - if (!iwqp->flush_issued) { + if (!atomic_read(&iwqp->flush_issued)) { if (iwqp->hw_iwarp_state <= IRDMA_QP_STATE_RTS) irdma_uk_qp_post_wr(ukqp); spin_unlock_irqrestore(&iwqp->lock, flags); @@ -2641,13 +2636,13 @@ irdma_post_recv(struct ib_qp *ibqp, "post_recv err %d\n", err); goto out; } - ib_wr = ib_wr->next; } out: spin_unlock_irqrestore(&iwqp->lock, flags); - if (iwqp->flush_issued) + + if (atomic_read(&iwqp->flush_issued)) irdma_sched_qp_flush_work(iwqp); if (err) @@ -2934,7 +2929,7 @@ irdma_req_notify_cq(struct ib_cq *ibcq, } if ((notify_flags & IB_CQ_REPORT_MISSED_EVENTS) && - (!irdma_cq_empty(iwcq) || !list_empty(&iwcq->cmpl_generated))) + (!irdma_uk_cq_empty(&iwcq->sc_cq.cq_uk) || !list_empty(&iwcq->cmpl_generated))) ret = 1; spin_unlock_irqrestore(&iwcq->lock, flags); @@ -3012,6 +3007,10 @@ irdma_mcast_cqp_op(struct irdma_device *iwdev, cqp_info->post_sq = 1; cqp_info->in.u.mc_create.scratch = (uintptr_t)cqp_request; cqp_info->in.u.mc_create.cqp = &iwdev->rf->cqp.sc_cqp; + + if (op == IRDMA_OP_MC_CREATE) + cqp_info->create = true; + status = irdma_handle_cqp_op(iwdev->rf, cqp_request); irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request); diff --git a/sys/dev/irdma/irdma_verbs.h b/sys/dev/irdma/irdma_verbs.h index 9a5b1cdb0381..d3f240783c3d 100644 --- a/sys/dev/irdma/irdma_verbs.h +++ b/sys/dev/irdma/irdma_verbs.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2015 - 2023 Intel Corporation + * Copyright (c) 2015 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -37,6 +37,7 @@ #define IRDMA_MAX_SAVED_PHY_PGADDR 4 #define IRDMA_FLUSH_DELAY_MS 20 +#define IRDMA_PERIODIC_FLUSH_MS 2000 #define IRDMA_PKEY_TBL_SZ 1 #define IRDMA_DEFAULT_PKEY 0xFFFF @@ -141,6 +142,7 @@ struct irdma_mr { int access; u8 is_hwreg; u16 type; + bool dma_mr:1; u32 page_cnt; u64 page_size; u64 page_msk; @@ -154,21 +156,15 @@ struct irdma_mr { struct irdma_cq { struct ib_cq ibcq; struct irdma_sc_cq sc_cq; - u16 cq_head; - u16 cq_size; - u16 cq_num; + u32 cq_num; bool user_mode; atomic_t armed; enum irdma_cmpl_notify last_notify; - u32 polled_cmpls; - u32 cq_mem_size; struct irdma_dma_mem kmem; struct irdma_dma_mem kmem_shadow; struct completion free_cq; atomic_t refcnt; spinlock_t lock; /* for poll cq */ - struct irdma_pbl *iwpbl; - struct irdma_pbl *iwpbl_shadow; struct list_head resize_list; struct irdma_cq_poll_info cur_cqe; struct list_head cmpl_generated; @@ -244,10 +240,12 @@ struct irdma_qp { dma_addr_t pbl_pbase; struct page *page; u8 iwarp_state; + atomic_t flush_issued; u16 term_sq_flush_code; u16 term_rq_flush_code; u8 hw_iwarp_state; u8 hw_tcp_state; + u8 ae_src; struct irdma_qp_kmode kqp; struct irdma_dma_mem host_ctx; struct timer_list terminate_timer; @@ -262,7 +260,6 @@ struct irdma_qp { bool active_conn:1; bool user_mode:1; bool hte_added:1; - bool flush_issued:1; bool sig_all:1; bool pau_mode:1; bool suspend_pending:1; @@ -385,6 +382,12 @@ static inline void irdma_mcast_mac_v6(u32 *ip_addr, u8 *mac) struct rdma_user_mmap_entry* irdma_user_mmap_entry_insert(struct irdma_ucontext *ucontext, u64 bar_offset, enum irdma_mmap_flag mmap_flag, u64 *mmap_offset); +struct irdma_mr *irdma_alloc_iwmr(struct ib_umem *region, + struct ib_pd *pd, u64 virt, + enum irdma_memreg_type reg_type); +void irdma_free_iwmr(struct irdma_mr *iwmr); +int irdma_reg_user_mr_type_mem(struct irdma_mr *iwmr, int access, + bool create_stag); int irdma_ib_register_device(struct irdma_device *iwdev); void irdma_ib_unregister_device(struct irdma_device *iwdev); void irdma_ib_qp_event(struct irdma_qp *iwqp, enum irdma_qp_event_type event); @@ -392,5 +395,7 @@ void irdma_generate_flush_completions(struct irdma_qp *iwqp); void irdma_remove_cmpls_list(struct irdma_cq *iwcq); int irdma_generated_cmpls(struct irdma_cq *iwcq, struct irdma_cq_poll_info *cq_poll_info); void irdma_sched_qp_flush_work(struct irdma_qp *iwqp); -void irdma_flush_worker(struct work_struct *work); +void irdma_kern_flush_worker(struct work_struct *work); +void irdma_user_flush_worker(struct work_struct *work); +int irdma_hw_alloc_mw(struct irdma_device *iwdev, struct irdma_mr *iwmr); #endif /* IRDMA_VERBS_H */ diff --git a/sys/dev/irdma/irdma_ws.c b/sys/dev/irdma/irdma_ws.c index d311343111b9..af781f23a22c 100644 --- a/sys/dev/irdma/irdma_ws.c +++ b/sys/dev/irdma/irdma_ws.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2017 - 2023 Intel Corporation + * Copyright (c) 2017 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -118,10 +118,11 @@ irdma_free_node(struct irdma_sc_vsi *vsi, * @vsi: vsi pointer * @node: pointer to node * @cmd: add, remove or modify + * @qs_handle: Pointer to store the qs_handle for a leaf node */ static int irdma_ws_cqp_cmd(struct irdma_sc_vsi *vsi, - struct irdma_ws_node *node, u8 cmd) + struct irdma_ws_node *node, u8 cmd, u16 *qs_handle) { struct irdma_ws_node_info node_info = {0}; @@ -142,10 +143,8 @@ irdma_ws_cqp_cmd(struct irdma_sc_vsi *vsi, return -ENOMEM; } - if (node->type_leaf && cmd == IRDMA_OP_WS_ADD_NODE) { - node->qs_handle = node_info.qs_handle; - vsi->qos[node->user_pri].qs_handle = node_info.qs_handle; - } + if (node->type_leaf && cmd == IRDMA_OP_WS_ADD_NODE && qs_handle) + *qs_handle = node_info.qs_handle; return 0; } @@ -193,11 +192,8 @@ irdma_ws_in_use(struct irdma_sc_vsi *vsi, u8 user_pri) { int i; - mutex_lock(&vsi->qos[user_pri].qos_mutex); - if (!list_empty(&vsi->qos[user_pri].qplist)) { - mutex_unlock(&vsi->qos[user_pri].qos_mutex); + if (!list_empty(&vsi->qos[user_pri].qplist)) return true; - } /* * Check if the qs handle associated with the given user priority is in use by any other user priority. If so, @@ -205,12 +201,9 @@ irdma_ws_in_use(struct irdma_sc_vsi *vsi, u8 user_pri) */ for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) { if (vsi->qos[i].qs_handle == vsi->qos[user_pri].qs_handle && - !list_empty(&vsi->qos[i].qplist)) { - mutex_unlock(&vsi->qos[user_pri].qos_mutex); + !list_empty(&vsi->qos[i].qplist)) return true; - } } - mutex_unlock(&vsi->qos[user_pri].qos_mutex); return false; } @@ -228,9 +221,10 @@ irdma_remove_leaf(struct irdma_sc_vsi *vsi, u8 user_pri) int i; qs_handle = vsi->qos[user_pri].qs_handle; - for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) + for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) { if (vsi->qos[i].qs_handle == qs_handle) vsi->qos[i].valid = false; + } ws_tree_root = vsi->dev->ws_tree_root; if (!ws_tree_root) @@ -247,25 +241,93 @@ irdma_remove_leaf(struct irdma_sc_vsi *vsi, u8 user_pri) if (!tc_node) return; - irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_DELETE_NODE); - vsi->unregister_qset(vsi, tc_node); list_del(&tc_node->siblings); + irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_DELETE_NODE, NULL); + + vsi->unregister_qset(vsi, tc_node); irdma_free_node(vsi, tc_node); /* Check if VSI node can be freed */ if (list_empty(&vsi_node->child_list_head)) { - irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_DELETE_NODE); + irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_DELETE_NODE, NULL); list_del(&vsi_node->siblings); irdma_free_node(vsi, vsi_node); /* Free head node there are no remaining VSI nodes */ if (list_empty(&ws_tree_root->child_list_head)) { irdma_ws_cqp_cmd(vsi, ws_tree_root, - IRDMA_OP_WS_DELETE_NODE); + IRDMA_OP_WS_DELETE_NODE, NULL); irdma_free_node(vsi, ws_tree_root); vsi->dev->ws_tree_root = NULL; } } } +static int +irdma_enable_leaf(struct irdma_sc_vsi *vsi, + struct irdma_ws_node *tc_node) +{ + int ret; + + ret = vsi->register_qset(vsi, tc_node); + if (ret) + return ret; + + tc_node->enable = true; + ret = irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_MODIFY_NODE, NULL); + if (ret) + goto enable_err; + return 0; + +enable_err: + vsi->unregister_qset(vsi, tc_node); + + return ret; +} + +static struct irdma_ws_node * +irdma_add_leaf_node(struct irdma_sc_vsi *vsi, + struct irdma_ws_node *vsi_node, + u8 user_pri, u16 traffic_class) +{ + struct irdma_ws_node *tc_node = + irdma_alloc_node(vsi, user_pri, WS_NODE_TYPE_LEAF, vsi_node); + int i, ret = 0; + + if (!tc_node) + return NULL; + ret = irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_ADD_NODE, &tc_node->qs_handle); + if (ret) { + irdma_free_node(vsi, tc_node); + return NULL; + } + vsi->qos[tc_node->user_pri].qs_handle = tc_node->qs_handle; + + list_add(&tc_node->siblings, &vsi_node->child_list_head); + + ret = irdma_enable_leaf(vsi, tc_node); + if (ret) + goto reg_err; + + /* + * Iterate through other UPs and update the QS handle if they have a matching traffic class. + */ + for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) { + if (vsi->qos[i].traffic_class == traffic_class) { + vsi->qos[i].qs_handle = tc_node->qs_handle; + vsi->qos[i].l2_sched_node_id = + tc_node->l2_sched_node_id; + vsi->qos[i].valid = true; + } + } + return tc_node; + +reg_err: + irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_DELETE_NODE, NULL); + list_del(&tc_node->siblings); + irdma_free_node(vsi, tc_node); + + return NULL; +} + /** * irdma_ws_add - Build work scheduler tree, set RDMA qs_handle * @vsi: vsi pointer @@ -279,7 +341,6 @@ irdma_ws_add(struct irdma_sc_vsi *vsi, u8 user_pri) struct irdma_ws_node *tc_node; u16 traffic_class; int ret = 0; - int i; mutex_lock(&vsi->dev->ws_mutex); if (vsi->tc_change_pending) { @@ -298,9 +359,11 @@ irdma_ws_add(struct irdma_sc_vsi *vsi, u8 user_pri) ret = -ENOMEM; goto exit; } - irdma_debug(vsi->dev, IRDMA_DEBUG_WS, "Creating root node = %d\n", ws_tree_root->index); + irdma_debug(vsi->dev, IRDMA_DEBUG_WS, + "Creating root node = %d\n", ws_tree_root->index); - ret = irdma_ws_cqp_cmd(vsi, ws_tree_root, IRDMA_OP_WS_ADD_NODE); + ret = irdma_ws_cqp_cmd(vsi, ws_tree_root, IRDMA_OP_WS_ADD_NODE, + NULL); if (ret) { irdma_free_node(vsi, ws_tree_root); goto exit; @@ -324,7 +387,8 @@ irdma_ws_add(struct irdma_sc_vsi *vsi, u8 user_pri) goto vsi_add_err; } - ret = irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_ADD_NODE); + ret = irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_ADD_NODE, + NULL); if (ret) { irdma_free_node(vsi, vsi_node); goto vsi_add_err; @@ -344,56 +408,22 @@ irdma_ws_add(struct irdma_sc_vsi *vsi, u8 user_pri) irdma_debug(vsi->dev, IRDMA_DEBUG_WS, "Node not found matching VSI %d and TC %d\n", vsi->vsi_idx, traffic_class); - tc_node = irdma_alloc_node(vsi, user_pri, WS_NODE_TYPE_LEAF, - vsi_node); + tc_node = irdma_add_leaf_node(vsi, vsi_node, user_pri, + traffic_class); if (!tc_node) { ret = -ENOMEM; goto leaf_add_err; } - - ret = irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_ADD_NODE); - if (ret) { - irdma_free_node(vsi, tc_node); - goto leaf_add_err; - } - - list_add(&tc_node->siblings, &vsi_node->child_list_head); - /* - * callback to LAN to update the LAN tree with our node - */ - ret = vsi->register_qset(vsi, tc_node); - if (ret) - goto reg_err; - - tc_node->enable = true; - ret = irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_MODIFY_NODE); - if (ret) { - vsi->unregister_qset(vsi, tc_node); - goto reg_err; - } } irdma_debug(vsi->dev, IRDMA_DEBUG_WS, "Using node %d which represents VSI %d TC %d\n", tc_node->index, vsi->vsi_idx, traffic_class); - /* - * Iterate through other UPs and update the QS handle if they have a matching traffic class. - */ - for (i = 0; i < IRDMA_MAX_USER_PRIORITY; i++) { - if (vsi->qos[i].traffic_class == traffic_class) { - vsi->qos[i].qs_handle = tc_node->qs_handle; - vsi->qos[i].l2_sched_node_id = tc_node->l2_sched_node_id; - vsi->qos[i].valid = true; - } - } goto exit; -reg_err: - irdma_ws_cqp_cmd(vsi, tc_node, IRDMA_OP_WS_DELETE_NODE); - list_del(&tc_node->siblings); - irdma_free_node(vsi, tc_node); leaf_add_err: if (list_empty(&vsi_node->child_list_head)) { - if (irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_DELETE_NODE)) + if (irdma_ws_cqp_cmd(vsi, vsi_node, IRDMA_OP_WS_DELETE_NODE, + NULL)) goto exit; list_del(&vsi_node->siblings); irdma_free_node(vsi, vsi_node); @@ -402,7 +432,8 @@ leaf_add_err: vsi_add_err: /* Free head node there are no remaining VSI nodes */ if (list_empty(&ws_tree_root->child_list_head)) { - irdma_ws_cqp_cmd(vsi, ws_tree_root, IRDMA_OP_WS_DELETE_NODE); + irdma_ws_cqp_cmd(vsi, ws_tree_root, IRDMA_OP_WS_DELETE_NODE, + NULL); vsi->dev->ws_tree_root = NULL; irdma_free_node(vsi, ws_tree_root); } @@ -420,12 +451,14 @@ exit: void irdma_ws_remove(struct irdma_sc_vsi *vsi, u8 user_pri) { + mutex_lock(&vsi->qos[user_pri].qos_mutex); mutex_lock(&vsi->dev->ws_mutex); if (irdma_ws_in_use(vsi, user_pri)) goto exit; irdma_remove_leaf(vsi, user_pri); exit: mutex_unlock(&vsi->dev->ws_mutex); + mutex_unlock(&vsi->qos[user_pri].qos_mutex); } /** diff --git a/sys/dev/irdma/osdep.h b/sys/dev/irdma/osdep.h index 831bd50f3ae4..eb73ffbd30e2 100644 --- a/sys/dev/irdma/osdep.h +++ b/sys/dev/irdma/osdep.h @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB * - * Copyright (c) 2021 - 2023 Intel Corporation + * Copyright (c) 2021 - 2026 Intel Corporation * * This software is available to you under a choice of one of two * licenses. You may choose to be licensed under the terms of the GNU @@ -85,13 +85,18 @@ #define STATS_TIMER_DELAY 60000 /* a couple of linux size defines */ -#define SZ_128 128 +#define SZ_128 128 #define SPEED_1000 1000 +#define SPEED_2500 2500 +#define SPEED_5000 5000 #define SPEED_10000 10000 +#define SPEED_14000 14000 #define SPEED_20000 20000 #define SPEED_25000 25000 #define SPEED_40000 40000 +#define SPEED_50000 50000 #define SPEED_100000 100000 +#define SPEED_200000 200000 #define irdma_mb() mb() #define irdma_wmb() wmb() diff --git a/sys/dev/isci/isci.c b/sys/dev/isci/isci.c index 1dede4e45b4c..b40350c36fca 100644 --- a/sys/dev/isci/isci.c +++ b/sys/dev/isci/isci.c @@ -72,7 +72,7 @@ static device_method_t isci_pci_methods[] = { DEVMETHOD(device_probe, isci_probe), DEVMETHOD(device_attach, isci_attach), DEVMETHOD(device_detach, isci_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t isci_pci_driver = { diff --git a/sys/dev/isci/scil/scic_sds_phy_registers.h b/sys/dev/isci/scil/scic_sds_phy_registers.h index c0467325eb3b..29b04133d19b 100644 --- a/sys/dev/isci/scil/scic_sds_phy_registers.h +++ b/sys/dev/isci/scil/scic_sds_phy_registers.h @@ -137,7 +137,7 @@ extern "C" { //***************************************************************************** /** - * THis macro requests the SCU register write for the specified link layer + * This macro requests the SCU register write for the specified link layer * register. */ #define scu_link_layer_register_read(phy, reg) \ diff --git a/sys/dev/isci/scil/scic_sds_remote_node_table.c b/sys/dev/isci/scil/scic_sds_remote_node_table.c index a29cbefa5057..e447d5d952af 100644 --- a/sys/dev/isci/scil/scic_sds_remote_node_table.c +++ b/sys/dev/isci/scil/scic_sds_remote_node_table.c @@ -276,7 +276,7 @@ void scic_sds_remote_node_table_clear_group( } /** - * THis method sets an entire remote node group in the remote node table. + * This method sets an entire remote node group in the remote node table. * * @param[in] remote_node_table * @param[in] group_index @@ -471,7 +471,7 @@ U16 scic_sds_remote_node_table_allocate_single_remote_node( * * @param[in] remote_node_table This is the remote node table from which to * allocate the remote node entries. - * @param[in] group_table_index THis is the group table index which must equal + * @param[in] group_table_index This is the group table index which must equal * two (2) for this operation. * * @return The remote node index that represents three consecutive remote node diff --git a/sys/dev/isci/scil/scic_sds_stp_request.h b/sys/dev/isci/scil/scic_sds_stp_request.h index e8a64868a3b1..8cf60c8dd1b3 100644 --- a/sys/dev/isci/scil/scic_sds_stp_request.h +++ b/sys/dev/isci/scil/scic_sds_stp_request.h @@ -175,7 +175,7 @@ enum SCIC_SDS_STP_REQUEST_STARTED_NON_DATA_SUBSTATES /** * @enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES * - * @brief THis enumeration depicts the various sub-states associated with a + * @brief This enumeration depicts the various sub-states associated with a * SATA/STP soft reset operation. */ enum SCIC_SDS_STP_REQUEST_STARTED_SOFT_RESET_SUBSTATES diff --git a/sys/dev/isci/scil/scif_remote_device.h b/sys/dev/isci/scil/scif_remote_device.h index b6ac032c8234..4c21654ce42a 100644 --- a/sys/dev/isci/scil/scif_remote_device.h +++ b/sys/dev/isci/scil/scif_remote_device.h @@ -240,7 +240,7 @@ SCI_REMOTE_DEVICE_HANDLE_T scif_remote_device_get_scic_handle( /** * @brief This method returns the maximum queue depth supported for the - * supplied target by this SCI Framework impementation. + * supplied target by this SCI Framework implementation. * * @param[in] remote_device This parameter specifies the framework * device for which to return the maximum queue depth. diff --git a/sys/dev/iscsi/icl_soft.c b/sys/dev/iscsi/icl_soft.c index 812793a9fba3..b03a88473187 100644 --- a/sys/dev/iscsi/icl_soft.c +++ b/sys/dev/iscsi/icl_soft.c @@ -166,7 +166,7 @@ static kobj_method_t icl_soft_methods[] = { #ifdef ICL_KERNEL_PROXY KOBJMETHOD(icl_conn_connect, icl_soft_conn_connect), #endif - { 0, 0 } + KOBJMETHOD_END }; DEFINE_CLASS(icl_soft, icl_soft_methods, sizeof(struct icl_soft_conn)); @@ -1112,7 +1112,7 @@ icl_soft_conn_pdu_append_bio(struct icl_conn *ic, struct icl_pdu *request, { struct icl_soft_pdu *isp = (struct icl_soft_pdu *)request; struct mbuf *m, *m_tail; - vm_offset_t vaddr; + char *vaddr; size_t mtodo, page_offset, todo; int i; @@ -1196,12 +1196,12 @@ icl_soft_conn_pdu_append_bio(struct icl_conn *ic, struct icl_pdu *request, while (len > 0) { todo = MIN(len, PAGE_SIZE - page_offset); - vaddr = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(bp->bio_ma[i])); + vaddr = VM_PAGE_TO_DMAP(bp->bio_ma[i]); do { mtodo = min(todo, M_SIZE(m) - m->m_len); - memcpy(mtod(m, char *) + m->m_len, (char *)vaddr + - page_offset, mtodo); + memcpy(mtod(m, char *) + m->m_len, vaddr + page_offset, + mtodo); m->m_len += mtodo; if (m->m_len == M_SIZE(m)) m = m->m_next; @@ -1269,7 +1269,7 @@ void icl_soft_conn_pdu_get_bio(struct icl_conn *ic, struct icl_pdu *ip, size_t pdu_off, struct bio *bp, size_t bio_off, size_t len) { - vm_offset_t vaddr; + char *vaddr; size_t page_offset, todo; int i __unused; @@ -1287,8 +1287,8 @@ icl_soft_conn_pdu_get_bio(struct icl_conn *ic, struct icl_pdu *ip, while (len > 0) { todo = MIN(len, PAGE_SIZE - page_offset); - vaddr = PHYS_TO_DMAP(VM_PAGE_TO_PHYS(bp->bio_ma[i])); - m_copydata(ip->ip_data_mbuf, pdu_off, todo, (char *)vaddr + + vaddr = VM_PAGE_TO_DMAP(bp->bio_ma[i]); + m_copydata(ip->ip_data_mbuf, pdu_off, todo, vaddr + page_offset); page_offset = 0; diff --git a/sys/dev/iser/icl_iser.c b/sys/dev/iser/icl_iser.c index f5e75849d470..627538081585 100644 --- a/sys/dev/iser/icl_iser.c +++ b/sys/dev/iser/icl_iser.c @@ -69,7 +69,7 @@ static kobj_method_t icl_iser_methods[] = { KOBJMETHOD(icl_conn_task_done, iser_conn_task_done), KOBJMETHOD(icl_conn_pdu_get_bio, iser_conn_pdu_get_bio), KOBJMETHOD(icl_conn_pdu_get_data, iser_conn_pdu_get_data), - { 0, 0 } + KOBJMETHOD_END }; DEFINE_CLASS(icl_iser, icl_iser_methods, sizeof(struct iser_conn)); diff --git a/sys/dev/isl/isl.c b/sys/dev/isl/isl.c index 6a0d406aeeda..815c189adee5 100644 --- a/sys/dev/isl/isl.c +++ b/sys/dev/isl/isl.c @@ -202,7 +202,7 @@ isl_attach(device_t dev) if (use_als) { SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "als", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, ISL_METHOD_ALS, isl_sysctl, "I", "Current ALS sensor read-out"); } @@ -210,7 +210,7 @@ isl_attach(device_t dev) if (use_ir) { SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "ir", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, ISL_METHOD_IR, isl_sysctl, "I", "Current IR sensor read-out"); } @@ -218,20 +218,20 @@ isl_attach(device_t dev) if (use_prox) { SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "prox", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, ISL_METHOD_PROX, isl_sysctl, "I", "Current proximity sensor read-out"); } SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "resolution", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, ISL_METHOD_RESOLUTION, isl_sysctl, "I", "Current proximity sensor resolution"); SYSCTL_ADD_PROC(sysctl_ctx, SYSCTL_CHILDREN(sysctl_tree), OID_AUTO, "range", - CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_NEEDGIANT, sc, + CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, sc, ISL_METHOD_RANGE, isl_sysctl, "I", "Current proximity sensor range"); diff --git a/sys/dev/isp/isp_pci.c b/sys/dev/isp/isp_pci.c index e8fd7b3cf571..4992379b1636 100644 --- a/sys/dev/isp/isp_pci.c +++ b/sys/dev/isp/isp_pci.c @@ -212,7 +212,7 @@ static device_method_t isp_pci_methods[] = { DEVMETHOD(device_probe, isp_pci_probe), DEVMETHOD(device_attach, isp_pci_attach), DEVMETHOD(device_detach, isp_pci_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t isp_pci_driver = { diff --git a/sys/dev/itwd/itwd.c b/sys/dev/itwd/itwd.c index 06120f1fdeac..ac3e521321c6 100644 --- a/sys/dev/itwd/itwd.c +++ b/sys/dev/itwd/itwd.c @@ -217,7 +217,7 @@ static device_method_t itwd_methods[] = { DEVMETHOD(device_detach, itwd_detach), /* Terminate method list */ - { 0, 0 } + DEVMETHOD_END }; static driver_t itwd_driver = { diff --git a/sys/dev/iwi/if_iwi.c b/sys/dev/iwi/if_iwi.c index 26b8037186a6..8146b513d4e6 100644 --- a/sys/dev/iwi/if_iwi.c +++ b/sys/dev/iwi/if_iwi.c @@ -2534,9 +2534,10 @@ iwi_setwepkeys(struct iwi_softc *sc, struct ieee80211vap *vap) wepkey.cmd = IWI_WEP_KEY_CMD_SETKEY; wepkey.idx = i; - wepkey.len = wk->wk_keylen; + wepkey.len = ieee80211_crypto_get_key_len(wk); memset(wepkey.key, 0, sizeof wepkey.key); - memcpy(wepkey.key, wk->wk_key, wk->wk_keylen); + memcpy(wepkey.key, ieee80211_crypto_get_key_data(wk), + ieee80211_crypto_get_key_len(wk)); DPRINTF(("Setting wep key index %u len %u\n", wepkey.idx, wepkey.len)); error = iwi_cmd(sc, IWI_CMD_SET_WEP_KEY, &wepkey, diff --git a/sys/dev/iwx/if_iwx.c b/sys/dev/iwx/if_iwx.c index 3c953e522973..03ef775205e7 100644 --- a/sys/dev/iwx/if_iwx.c +++ b/sys/dev/iwx/if_iwx.c @@ -155,6 +155,7 @@ #include <sys/epoch.h> #include <sys/kdb.h> +#include <machine/_inttypes.h> #include <machine/bus.h> #include <machine/endian.h> #include <machine/resource.h> @@ -5818,15 +5819,21 @@ iwx_tx(struct iwx_softc *sc, struct mbuf *m, struct ieee80211_node *ni) desc->tbs[0].tb_len = htole16(IWX_FIRST_TB_SIZE); paddr = htole64(data->cmd_paddr); memcpy(&desc->tbs[0].addr, &paddr, sizeof(paddr)); - if (data->cmd_paddr >> 32 != (data->cmd_paddr + le32toh(desc->tbs[0].tb_len)) >> 32) +#if __SIZEOF_SIZE_T__ > 4 + if (data->cmd_paddr >> 32 != (data->cmd_paddr + + le32toh(desc->tbs[0].tb_len)) >> 32) DPRINTF(("%s: TB0 crosses 32bit boundary\n", __func__)); +#endif desc->tbs[1].tb_len = htole16(sizeof(struct iwx_cmd_header) + txcmd_size + hdrlen + pad - IWX_FIRST_TB_SIZE); paddr = htole64(data->cmd_paddr + IWX_FIRST_TB_SIZE); memcpy(&desc->tbs[1].addr, &paddr, sizeof(paddr)); - if (data->cmd_paddr >> 32 != (data->cmd_paddr + le32toh(desc->tbs[1].tb_len)) >> 32) +#if __SIZEOF_SIZE_T__ > 4 + if (data->cmd_paddr >> 32 != (data->cmd_paddr + + le32toh(desc->tbs[1].tb_len)) >> 32) DPRINTF(("%s: TB1 crosses 32bit boundary\n", __func__)); +#endif /* Other DMA segments are for data payload. */ for (i = 0; i < nsegs; i++) { @@ -5834,8 +5841,12 @@ iwx_tx(struct iwx_softc *sc, struct mbuf *m, struct ieee80211_node *ni) desc->tbs[i + 2].tb_len = htole16(seg->ds_len); paddr = htole64(seg->ds_addr); memcpy(&desc->tbs[i + 2].addr, &paddr, sizeof(paddr)); - if (data->cmd_paddr >> 32 != (data->cmd_paddr + le32toh(desc->tbs[i + 2].tb_len)) >> 32) - DPRINTF(("%s: TB%d crosses 32bit boundary\n", __func__, i + 2)); +#if __SIZEOF_SIZE_T__ > 4 + if (data->cmd_paddr >> 32 != (data->cmd_paddr + + le32toh(desc->tbs[i + 2].tb_len)) >> 32) + DPRINTF(("%s: TB%d crosses 32bit boundary\n", __func__, + i + 2)); +#endif } bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_PREWRITE); @@ -11069,16 +11080,18 @@ iwx_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k) IWX_UNLOCK(sc); return (ENXIO); } - memcpy(cmd.common.key, k->wk_key, MIN(sizeof(cmd.common.key), - k->wk_keylen)); + memcpy(cmd.common.key, ieee80211_crypto_get_key_data(k), + MIN(sizeof(cmd.common.key), ieee80211_crypto_get_key_len(k))); IWX_DPRINTF(sc, IWX_DEBUG_KEYMGMT, "%s: key: id=%d, len=%i, key=%*D\n", - __func__, id, k->wk_keylen, k->wk_keylen, - (const unsigned char *) k->wk_key, ""); + __func__, id, + ieee80211_crypto_get_key_len(k), + ieee80211_crypto_get_key_len(k), + (const unsigned char *) ieee80211_crypto_get_key_data(k), ""); cmd.common.sta_id = IWX_STATION_ID; cmd.transmit_seq_cnt = htole64(k->wk_keytsc); - IWX_DPRINTF(sc, IWX_DEBUG_KEYMGMT, "%s: k->wk_keytsc=%lu\n", __func__, - k->wk_keytsc); + IWX_DPRINTF(sc, IWX_DEBUG_KEYMGMT, "%s: k->wk_keytsc=%" PRIu64 "\n", + __func__, k->wk_keytsc); status = IWX_ADD_STA_SUCCESS; err = iwx_send_cmd_pdu_status(sc, IWX_ADD_STA_KEY, sizeof(cmd), &cmd, diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index 1d36fd11f368..b9d88fcab523 100644 --- a/sys/dev/ixgbe/if_ix.c +++ b/sys/dev/ixgbe/if_ix.c @@ -36,10 +36,14 @@ #include "opt_rss.h" #include "ixgbe.h" +#include "mdio_if.h" #include "ixgbe_sriov.h" #include "ifdi_if.h" +#include "if_ix_mdio_hw.h" +#include "if_ix_mdio.h" #include <net/netmap.h> +#include <dev/mdio/mdio.h> #include <dev/netmap/netmap_kern.h> /************************************************************************ @@ -298,6 +302,10 @@ static device_method_t ix_methods[] = { DEVMETHOD(pci_iov_uninit, iflib_device_iov_uninit), DEVMETHOD(pci_iov_add_vf, iflib_device_iov_add_vf), #endif /* PCI_IOV */ + DEVMETHOD(bus_add_child, device_add_child_ordered), + DEVMETHOD(mdio_readreg, ixgbe_mdio_readreg_c22), + DEVMETHOD(mdio_writereg, ixgbe_mdio_writereg_c22), + DEVMETHOD_END }; @@ -305,11 +313,13 @@ static driver_t ix_driver = { "ix", ix_methods, sizeof(struct ixgbe_softc), }; -DRIVER_MODULE(ix, pci, ix_driver, 0, 0); +DRIVER_MODULE(mdio, ix, mdio_driver, 0, 0); /* needs to happen before ix */ +DRIVER_MODULE_ORDERED(ix, pci, ix_driver, NULL, NULL, SI_ORDER_ANY); /* needs to be last */ IFLIB_PNP_INFO(pci, ix_driver, ixgbe_vendor_info_array); MODULE_DEPEND(ix, pci, 1, 1, 1); MODULE_DEPEND(ix, ether, 1, 1, 1); MODULE_DEPEND(ix, iflib, 1, 1, 1); +MODULE_DEPEND(ix, mdio, 1, 1, 1); static device_method_t ixgbe_if_methods[] = { DEVMETHOD(ifdi_attach_pre, ixgbe_if_attach_pre), @@ -709,7 +719,7 @@ ixgbe_initialize_rss_mapping(struct ixgbe_softc *sc) RSS_HASHTYPE_RSS_TCP_IPV6_EX; } - mrqc = IXGBE_MRQC_RSSEN; + mrqc = ixgbe_get_mrqc(sc->iov_mode); if (rss_hash_config & RSS_HASHTYPE_RSS_IPV4) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV4; if (rss_hash_config & RSS_HASHTYPE_RSS_TCP_IPV4) @@ -728,7 +738,7 @@ ixgbe_initialize_rss_mapping(struct ixgbe_softc *sc) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_UDP; if (rss_hash_config & RSS_HASHTYPE_RSS_UDP_IPV6_EX) mrqc |= IXGBE_MRQC_RSS_FIELD_IPV6_EX_UDP; - mrqc |= ixgbe_get_mrqc(sc->iov_mode); + IXGBE_WRITE_REG(hw, IXGBE_MRQC, mrqc); } /* ixgbe_initialize_rss_mapping */ @@ -1066,6 +1076,10 @@ ixgbe_if_attach_pre(if_ctx_t ctx) /* Ensure SW/FW semaphore is free */ ixgbe_init_swfw_semaphore(hw); + /* Enable EEE power saving */ + if (sc->feat_en & IXGBE_FEATURE_EEE) + hw->mac.ops.setup_eee(hw, true); + /* Set an initial default flow control value */ hw->fc.requested_mode = ixgbe_flow_control; @@ -1118,10 +1132,13 @@ ixgbe_if_attach_pre(if_ctx_t ctx) break; } - /* Check the FW API version */ - if (hw->mac.type == ixgbe_mac_E610 && ixgbe_check_fw_api_version(sc)) { - error = EIO; - goto err_pci; + /* Check the FW API version and enable FW logging support for E610 */ + if (hw->mac.type == ixgbe_mac_E610) { + if (ixgbe_check_fw_api_version(sc)) { + error = EIO; + goto err_pci; + } + ixgbe_fwlog_set_support_ena(hw); } /* Most of the iflib initialization... */ @@ -1267,6 +1284,9 @@ ixgbe_if_attach_post(if_ctx_t ctx) /* Add sysctls */ ixgbe_add_device_sysctls(ctx); + /* Add MDIO bus if required / supported */ + ixgbe_mdio_attach(sc); + /* Init recovery mode timer and state variable */ if (sc->feat_en & IXGBE_FEATURE_RECOVERY_MODE) { sc->recovery_mode = 0; @@ -3395,6 +3415,9 @@ ixgbe_add_debug_sysctls(struct ixgbe_softc *sc) if (sc->feat_en & IXGBE_FEATURE_DBG_DUMP) ixgbe_add_debug_dump_sysctls(sc); + + if (sc->feat_en & IXGBE_FEATURE_FW_LOGGING) + ixgbe_add_fw_logging_tunables(sc, sc->debug_sysctls); } /* ixgbe_add_debug_sysctls */ /************************************************************************ @@ -4491,6 +4514,10 @@ ixgbe_handle_fw_event(void *context) sc->task_requests |= IXGBE_REQUEST_TASK_LSC; break; + case ixgbe_aci_opc_fw_logs_event: + ixgbe_fwlog_event_dump(&sc->hw, &event.desc, event.msg_buf); + break; + case ixgbe_aci_opc_temp_tca_event: if (hw->adapter_stopped == FALSE) ixgbe_if_stop(ctx); @@ -4589,6 +4616,20 @@ ixgbe_if_update_admin_status(if_ctx_t ctx) "Link is up %s Full Duplex\n", ixgbe_link_speed_to_str(sc->link_speed)); sc->link_active = true; + + /* If link speed is <= 1Gbps and EEE is enabled, + * log info. + */ + if (sc->hw.mac.type == ixgbe_mac_E610 && + (sc->feat_en & IXGBE_FEATURE_EEE) && + sc->link_speed <= IXGBE_LINK_SPEED_1GB_FULL) { + device_printf(sc->dev, + "Energy Efficient Ethernet (EEE) feature " + "is not supported on link speeds equal to " + "or below 1Gbps. EEE is supported on " + "speeds above 1Gbps.\n"); + } + /* Update any Flow Control changes */ ixgbe_fc_enable(&sc->hw); /* Update DMA coalescing config */ @@ -5582,6 +5623,17 @@ ixgbe_sysctl_eee_state(SYSCTL_HANDLER_ARGS) if ((new_eee < 0) || (new_eee > 1)) return (EINVAL); + /* If link speed is <= 1Gbps and EEE is being enabled, log info */ + if (sc->hw.mac.type == ixgbe_mac_E610 && + new_eee && + sc->link_speed <= IXGBE_LINK_SPEED_1GB_FULL) { + device_printf(dev, + "Energy Efficient Ethernet (EEE) feature is not " + "supported on link speeds equal to or below 1Gbps. " + "EEE is supported on speeds above 1Gbps.\n"); + return (EINVAL); + } + retval = ixgbe_setup_eee(&sc->hw, new_eee); if (retval) { device_printf(dev, "Error in EEE setup: 0x%08X\n", retval); @@ -5645,6 +5697,8 @@ ixgbe_sysctl_tso_tcp_flags_mask(SYSCTL_HANDLER_ARGS) static void ixgbe_init_device_features(struct ixgbe_softc *sc) { + s32 error; + sc->feat_cap = IXGBE_FEATURE_NETMAP | IXGBE_FEATURE_RSS | IXGBE_FEATURE_MSI | @@ -5700,6 +5754,10 @@ ixgbe_init_device_features(struct ixgbe_softc *sc) case ixgbe_mac_E610: sc->feat_cap |= IXGBE_FEATURE_RECOVERY_MODE; sc->feat_cap |= IXGBE_FEATURE_DBG_DUMP; + sc->feat_cap |= IXGBE_FEATURE_FW_LOGGING; + error = ixgbe_get_caps(&sc->hw); + if (error == 0 && sc->hw.func_caps.common_cap.eee_support != 0) + sc->feat_cap |= IXGBE_FEATURE_EEE; break; default: break; @@ -5724,6 +5782,9 @@ ixgbe_init_device_features(struct ixgbe_softc *sc) /* FW Debug Dump */ if (sc->feat_cap & IXGBE_FEATURE_DBG_DUMP) sc->feat_en |= IXGBE_FEATURE_DBG_DUMP; + /* FW Logging */ + if (sc->feat_cap & IXGBE_FEATURE_FW_LOGGING) + sc->feat_en |= IXGBE_FEATURE_FW_LOGGING; /* Enabled via global sysctl... */ /* Flow Director */ diff --git a/sys/dev/ixgbe/if_ix_mdio.c b/sys/dev/ixgbe/if_ix_mdio.c new file mode 100644 index 000000000000..3aa7ea80c3a7 --- /dev/null +++ b/sys/dev/ixgbe/if_ix_mdio.c @@ -0,0 +1,158 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opt_inet.h" +#include "opt_inet6.h" +#include "opt_rss.h" + +#include "ixgbe.h" +#include "mdio_if.h" +#include "ixgbe_sriov.h" +#include "ifdi_if.h" +#include "if_ix_mdio_hw.h" +#include "if_ix_mdio.h" + +#include <dev/mdio/mdio.h> + +/** + * @brief Return if the given ixgbe chipset supports clause 22 MDIO bus access. + * + * Although technically all of the ixgbe chipsets support an MDIO + * bus interface, there's a bunch of factors controlling whether + * this should be exposed for external control. + * + * This functionr returns true if it supports an MDIO bus and + * clause 22 transactions. + */ +static bool +ixgbe_has_mdio_bus_clause22(struct ixgbe_hw *hw) +{ + switch (hw->device_id) { + case IXGBE_DEV_ID_X550EM_A_KR: + case IXGBE_DEV_ID_X550EM_A_KR_L: + case IXGBE_DEV_ID_X550EM_A_SFP_N: + case IXGBE_DEV_ID_X550EM_A_SGMII: + case IXGBE_DEV_ID_X550EM_A_SGMII_L: + case IXGBE_DEV_ID_X550EM_A_10G_T: + case IXGBE_DEV_ID_X550EM_A_SFP: + case IXGBE_DEV_ID_X550EM_A_1G_T: + case IXGBE_DEV_ID_X550EM_A_1G_T_L: + return (true); + } + return (false); +} + + + +/** + * @brief Initiate a clause-22 MDIO read transfer. + * + * Note this is only officially supported for a small subset + * of NICs, notably the X552/X553 devices. This must not be + * called for other chipsets. + */ +int +ixgbe_mdio_readreg_c22(device_t dev, int phy, int reg) +{ + if_ctx_t ctx = device_get_softc(dev); + struct sx *iflib_ctx_lock = iflib_ctx_lock_get(ctx); + struct ixgbe_softc *sc = iflib_get_softc(ctx); + struct ixgbe_hw *hw = &sc->hw; + uint16_t val = 0; + int32_t ret = 0; + + if (! ixgbe_has_mdio_bus_clause22(hw)) + return (-1); + + sx_xlock(iflib_ctx_lock); + ret = ixgbe_read_mdio_c22(hw, phy, reg, &val); + if (ret != IXGBE_SUCCESS) { + device_printf(dev, "%s: read_mdi_22 failed (%d)\n", + __func__, ret); + sx_xunlock(iflib_ctx_lock); + return (-1); + } + sx_xunlock(iflib_ctx_lock); + return (val); +} + +/** + * @brief Initiate a clause-22 MDIO write transfer. + * + * Note this is only officially supported for a small subset + * of NICs, notably the X552/X553 devices. This must not be + * called for other chipsets. + */ +int +ixgbe_mdio_writereg_c22(device_t dev, int phy, int reg, int data) +{ + if_ctx_t ctx = device_get_softc(dev); + struct sx *iflib_ctx_lock = iflib_ctx_lock_get(ctx); + struct ixgbe_softc *sc = iflib_get_softc(ctx); + struct ixgbe_hw *hw = &sc->hw; + int32_t ret; + + if (! ixgbe_has_mdio_bus_clause22(hw)) + return (-1); + + sx_xlock(iflib_ctx_lock); + ret = ixgbe_write_mdio_c22(hw, phy, reg, data); + if (ret != IXGBE_SUCCESS) { + device_printf(dev, "%s: write_mdi_22 failed (%d)\n", + __func__, ret); + sx_xunlock(iflib_ctx_lock); + return (-1); + } + sx_xunlock(iflib_ctx_lock); + return (0); +} + +/** + * @brief Attach the MDIO bus if one exists. + */ +void +ixgbe_mdio_attach(struct ixgbe_softc *sc) +{ + struct ixgbe_hw *hw = &sc->hw; + int enable_mdio = 0; + + /* + * This explicitly needs to be enabled regardless of whether + * the device / instance supports an external MDIO bus. + */ + if (resource_int_value(device_get_name(sc->dev), + device_get_unit(sc->dev), "enable_mdio", &enable_mdio) == 0) { + if (enable_mdio == 0) + return; + } else + return; + + if (! ixgbe_has_mdio_bus_clause22(hw)) + return; + + device_add_child(sc->dev, "mdio", DEVICE_UNIT_ANY); + bus_attach_children(sc->dev); +} diff --git a/sys/dev/ixgbe/if_ix_mdio.h b/sys/dev/ixgbe/if_ix_mdio.h new file mode 100644 index 000000000000..f9fe99275b2b --- /dev/null +++ b/sys/dev/ixgbe/if_ix_mdio.h @@ -0,0 +1,34 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _IF_IX_MDIO_H_ +#define _IF_IX_MDIO_H_ + +int ixgbe_mdio_readreg_c22(device_t, int, int); +int ixgbe_mdio_writereg_c22(device_t, int, int, int); +void ixgbe_mdio_attach(struct ixgbe_softc *); + +#endif /* _IF_IX_MDIO_H */ diff --git a/sys/dev/ixgbe/if_ix_mdio_hw.c b/sys/dev/ixgbe/if_ix_mdio_hw.c new file mode 100644 index 000000000000..581ed09f27e3 --- /dev/null +++ b/sys/dev/ixgbe/if_ix_mdio_hw.c @@ -0,0 +1,181 @@ +/****************************************************************************** + SPDX-License-Identifier: BSD-3-Clause + + Copyright (c) 2001-2024, Intel Corporation + All rights reserved. + Copyright (c) 2026 Adrian Chadd <adrian@FreeBSD.org> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. Neither the name of the Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. + +******************************************************************************/ + +#include "ixgbe_api.h" +#include "ixgbe_common.h" +#include "ixgbe_phy.h" + +#include "if_ix_mdio_hw.h" + +/* + * These routines are separate from the rest of ixgbe for now to make merging + * easier. + */ + +static s32 +ixgbe_read_mdio_unlocked_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 *phy_data) +{ + u32 i, data, command; + + /* Setup and write the read command */ + command = (reg << IXGBE_MSCA_DEV_TYPE_SHIFT) | + (phy << IXGBE_MSCA_PHY_ADDR_SHIFT) | + IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_READ_AUTOINC | + IXGBE_MSCA_MDI_COMMAND; + + IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); + + /* Check every 10 usec to see if the access completed. + * The MDI Command bit will clear when the operation is + * complete + */ + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { + usec_delay(10); + + command = IXGBE_READ_REG(hw, IXGBE_MSCA); + if (!(command & IXGBE_MSCA_MDI_COMMAND)) + break; + } + + if (command & IXGBE_MSCA_MDI_COMMAND) + return IXGBE_ERR_PHY; + + /* Read operation is complete. Get the data from MSRWD */ + data = IXGBE_READ_REG(hw, IXGBE_MSRWD); + data >>= IXGBE_MSRWD_READ_DATA_SHIFT; + *phy_data = (u16)data; + + return IXGBE_SUCCESS; +} + +static s32 +ixgbe_write_mdio_unlocked_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 phy_data) +{ + u32 i, command; + + /* Put the data in the MDI single read and write data register*/ + IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)phy_data); + + /* Setup and write the write command */ + command = (reg << IXGBE_MSCA_DEV_TYPE_SHIFT) | + (phy << IXGBE_MSCA_PHY_ADDR_SHIFT) | + IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE | + IXGBE_MSCA_MDI_COMMAND; + + IXGBE_WRITE_REG(hw, IXGBE_MSCA, command); + + /* Check every 10 usec to see if the access completed. + * The MDI Command bit will clear when the operation is + * complete + */ + for (i = 0; i < IXGBE_MDIO_COMMAND_TIMEOUT; i++) { + usec_delay(10); + + command = IXGBE_READ_REG(hw, IXGBE_MSCA); + if (!(command & IXGBE_MSCA_MDI_COMMAND)) + break; + } + + if (command & IXGBE_MSCA_MDI_COMMAND) + return IXGBE_ERR_PHY; + + return IXGBE_SUCCESS; +} + +/* + * Return true if the MAC is an X55x backplane. + * + * These have a single MDIO PHY semaphore (PHY0) and also require the + * token semaphore. + */ +static bool +ixgbe_check_mdio_is_x550em(struct ixgbe_hw *hw) +{ + + switch (hw->device_id) { + case IXGBE_DEV_ID_X550EM_A_KR: + case IXGBE_DEV_ID_X550EM_A_KR_L: + case IXGBE_DEV_ID_X550EM_A_SFP_N: + case IXGBE_DEV_ID_X550EM_A_SGMII: + case IXGBE_DEV_ID_X550EM_A_SGMII_L: + case IXGBE_DEV_ID_X550EM_A_10G_T: + case IXGBE_DEV_ID_X550EM_A_SFP: + case IXGBE_DEV_ID_X550EM_A_1G_T: + case IXGBE_DEV_ID_X550EM_A_1G_T_L: + return true; + default: + return false; + } +} + +s32 +ixgbe_read_mdio_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 *phy_data) +{ + u32 gssr = hw->phy.phy_semaphore_mask; + s32 ret; + + if (ixgbe_check_mdio_is_x550em(hw)) + gssr |= IXGBE_GSSR_PHY0_SM | IXGBE_GSSR_TOKEN_SM; + + if (hw->mac.ops.acquire_swfw_sync(hw, gssr)) { + *phy_data = -1; + return IXGBE_ERR_TIMEOUT; + } + + ret = ixgbe_read_mdio_unlocked_c22(hw, phy, reg, phy_data); + if (ret != IXGBE_SUCCESS) + *phy_data = -1; + + hw->mac.ops.release_swfw_sync(hw, gssr); + return ret; +} + +s32 +ixgbe_write_mdio_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 data) +{ + u32 gssr = hw->phy.phy_semaphore_mask; + s32 ret; + + if (ixgbe_check_mdio_is_x550em(hw)) + gssr |= IXGBE_GSSR_PHY0_SM | IXGBE_GSSR_TOKEN_SM; + + if (hw->mac.ops.acquire_swfw_sync(hw, gssr)) + return IXGBE_ERR_TIMEOUT; + + ret = ixgbe_write_mdio_unlocked_c22(hw, phy, reg, data); + + hw->mac.ops.release_swfw_sync(hw, gssr); + return ret; +} diff --git a/sys/dev/ixgbe/if_ix_mdio_hw.h b/sys/dev/ixgbe/if_ix_mdio_hw.h new file mode 100644 index 000000000000..b2db5d431819 --- /dev/null +++ b/sys/dev/ixgbe/if_ix_mdio_hw.h @@ -0,0 +1,33 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Adrian Chadd <adrian@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _IF_IX_MDIO_HW_H_ +#define _IF_IX_MDIO_HW_H_ + +s32 ixgbe_read_mdio_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 *phy_data); +s32 ixgbe_write_mdio_c22(struct ixgbe_hw *hw, u16 phy, u16 reg, u16 data); + +#endif /* _IF_IX_MDIO_HW_H_ */ diff --git a/sys/dev/ixgbe/if_sriov.c b/sys/dev/ixgbe/if_sriov.c index 1998cdb016f7..47f1a1279e2f 100644 --- a/sys/dev/ixgbe/if_sriov.c +++ b/sys/dev/ixgbe/if_sriov.c @@ -170,7 +170,7 @@ ixgbe_get_mrqc(int iov_mode) mrqc = IXGBE_MRQC_VMDQRSS32EN; break; case IXGBE_NO_VM: - mrqc = 0; + mrqc = IXGBE_MRQC_RSSEN; break; default: panic("Unexpected SR-IOV mode %d", iov_mode); diff --git a/sys/dev/ixgbe/ixgbe.h b/sys/dev/ixgbe/ixgbe.h index 624b71acabea..9120ca5a37ff 100644 --- a/sys/dev/ixgbe/ixgbe.h +++ b/sys/dev/ixgbe/ixgbe.h @@ -607,6 +607,11 @@ int ixgbe_setup_receive_structures(struct ixgbe_softc *); void ixgbe_free_receive_structures(struct ixgbe_softc *); int ixgbe_get_regs(SYSCTL_HANDLER_ARGS); +void ixgbe_add_fw_logging_tunables(struct ixgbe_softc *sc, + struct sysctl_oid *parent); + +#define IXGBE_STR_BUF_LEN 32 + #include "ixgbe_bypass.h" #include "ixgbe_fdir.h" #include "ixgbe_rss.h" diff --git a/sys/dev/ixgbe/ixgbe_common.c b/sys/dev/ixgbe/ixgbe_common.c index bff022585a03..9e827d2e5473 100644 --- a/sys/dev/ixgbe/ixgbe_common.c +++ b/sys/dev/ixgbe/ixgbe_common.c @@ -4631,11 +4631,11 @@ s32 ixgbe_hic_unlocked(struct ixgbe_hw *hw, u32 *buffer, u32 length, /* Setting this bit tells the ARC that a new command is pending. */ IXGBE_WRITE_REG(hw, IXGBE_HICR, hicr | IXGBE_HICR_C); - for (i = 0; i < timeout; i++) { + for (i = 0; i < timeout * 1000; i++) { hicr = IXGBE_READ_REG(hw, IXGBE_HICR); if (!(hicr & IXGBE_HICR_C)) break; - msec_delay(1); + usec_delay(1); } /* For each command except "Apply Update" perform diff --git a/sys/dev/ixgbe/ixgbe_e610.c b/sys/dev/ixgbe/ixgbe_e610.c index 18c4612446e0..21066f95a16e 100644 --- a/sys/dev/ixgbe/ixgbe_e610.c +++ b/sys/dev/ixgbe/ixgbe_e610.c @@ -776,6 +776,10 @@ ixgbe_parse_common_caps(struct ixgbe_hw *hw, struct ixgbe_hw_common_caps *caps, DEBUGOUT2("%s: next_cluster_id_support = %d\n", prefix, caps->next_cluster_id_support); break; + case IXGBE_ACI_CAPS_EEE: + caps->eee_support = (u8)number; + DEBUGOUT2("%s: eee_support = %x\n", prefix, caps->eee_support); + break; default: /* Not one of the recognized common capabilities */ found = false; @@ -1332,6 +1336,7 @@ void ixgbe_copy_phy_caps_to_cfg(struct ixgbe_aci_cmd_get_phy_caps_data *caps, cfg->link_fec_opt = caps->link_fec_options; cfg->module_compliance_enforcement = caps->module_compliance_enforcement; + cfg->eee_entry_delay = caps->eee_entry_delay; } /** @@ -1351,10 +1356,12 @@ s32 ixgbe_aci_set_phy_cfg(struct ixgbe_hw *hw, struct ixgbe_aci_cmd_set_phy_cfg_data *cfg) { struct ixgbe_aci_desc desc; + bool use_1p40_buff; s32 status; if (!cfg) return IXGBE_ERR_PARAM; + use_1p40_buff = hw->func_caps.common_cap.eee_support != 0; /* Ensure that only valid bits of cfg->caps can be turned on. */ if (cfg->caps & ~IXGBE_ACI_PHY_ENA_VALID_MASK) { @@ -1364,8 +1371,18 @@ s32 ixgbe_aci_set_phy_cfg(struct ixgbe_hw *hw, ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_set_phy_cfg); desc.flags |= IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_RD); - status = ixgbe_aci_send_cmd(hw, &desc, cfg, sizeof(*cfg)); + if (use_1p40_buff) { + status = ixgbe_aci_send_cmd(hw, &desc, cfg, sizeof(*cfg)); + } else { + struct ixgbe_aci_cmd_set_phy_cfg_data_pre_1_40 cfg_obsolete; + + memcpy(&cfg_obsolete, cfg, sizeof(cfg_obsolete)); + + status = ixgbe_aci_send_cmd(hw, &desc, &cfg_obsolete, + sizeof(cfg_obsolete)); + } + /* even if the old buffer is used no need to worry about conversion */ if (!status) hw->phy.curr_user_phy_cfg = *cfg; @@ -1599,6 +1616,7 @@ s32 ixgbe_aci_get_link_info(struct ixgbe_hw *hw, bool ena_lse, li->topo_media_conflict = link_data.topo_media_conflict; li->pacing = link_data.cfg & (IXGBE_ACI_CFG_PACING_M | IXGBE_ACI_CFG_PACING_TYPE_M); + li->eee_status = link_data.eee_status; /* update fc info */ tx_pause = !!(link_data.an_info & IXGBE_ACI_LINK_PAUSE_TX); @@ -3812,6 +3830,492 @@ s32 ixgbe_handle_nvm_access(struct ixgbe_hw *hw, } /** + * ixgbe_fwlog_cache_cfg - Cache FW logging config + * @hw: pointer to the HW structure + * @cfg: config to cache + * + * Cache FW logging config. + */ +static void ixgbe_fwlog_cache_cfg(struct ixgbe_hw *hw, + struct ixgbe_fwlog_cfg *cfg) +{ + hw->fwlog_cfg = *cfg; +} + +/** + * ixgbe_fwlog_valid_module_entries - validate all the module entry IDs and + * log levels + * @hw: pointer to the HW structure + * @entries: entries to validate + * @num_entries: number of entries to validate + * + * Checks if all the module entry IDs and log levels are valid. + * + * Return: true if all the module entry IDs and log levels are valid, + * otherwise false. + */ +static bool ixgbe_fwlog_valid_module_entries(struct ixgbe_hw *hw, + struct ixgbe_fwlog_module_entry *entries, + u16 num_entries) +{ + u16 i; + + UNREFERENCED_1PARAMETER(hw); + + if (!entries) { + return false; + } + + if (!num_entries) { + return false; + } + + for (i = 0; i < num_entries; i++) { + struct ixgbe_fwlog_module_entry *entry = &entries[i]; + + if (entry->module_id >= IXGBE_ACI_FW_LOG_ID_MAX) { + return false; + } + + if (entry->log_level >= IXGBE_FWLOG_LEVEL_INVALID) { + return false; + } + } + + return true; +} + +/** + * ixgbe_fwlog_valid_cfg - validate configuration + * @hw: pointer to the HW structure + * @cfg: config to validate + * + * Validate the entire configuration. + * + * Return: true if the entire configuration is valid, otherwise false. + */ +static bool ixgbe_fwlog_valid_cfg(struct ixgbe_hw *hw, + struct ixgbe_fwlog_cfg *cfg) +{ + if (!cfg) { + return false; + } + + if (cfg->log_resolution < IXGBE_ACI_FW_LOG_MIN_RESOLUTION || + cfg->log_resolution > IXGBE_ACI_FW_LOG_MAX_RESOLUTION) { + return false; + } + + if (!ixgbe_fwlog_valid_module_entries(hw, cfg->module_entries, + IXGBE_ACI_FW_LOG_ID_MAX)) + return false; + + return true; +} + +/** + * ixgbe_fwlog_init - Initialize cached structures for tracking FW logging + * @hw: pointer to the HW structure + * @cfg: config used to initialize the cached structures + * + * Initialize cached structures for tracking FW logging + * Called on driver initialization and before calling + * ixgbe_init_hw(). Firmware logging will be configured based on these settings + * and also the PF will be registered on init. + * + * Return: the exit code of the operation. + */ +s32 ixgbe_fwlog_init(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg) +{ + if (!ixgbe_fwlog_valid_cfg(hw, cfg)) + return IXGBE_ERR_PARAM; + + ixgbe_fwlog_cache_cfg(hw, cfg); + + return IXGBE_SUCCESS; +} + +/** + * ixgbe_aci_fwlog_set - Set FW logging configuration + * @hw: pointer to the HW structure + * @entries: entries to configure + * @num_entries: number of @entries + * @options: options from ixgbe_fwlog_cfg->options structure + * @log_resolution: logging resolution + * + * Set FW logging configuration using ACI command (0xFF30). + * + * Return: the exit code of the operation. + */ +static s32 ixgbe_aci_fwlog_set(struct ixgbe_hw *hw, + struct ixgbe_fwlog_module_entry *entries, + u16 num_entries, u16 options, u16 log_resolution) +{ + struct ixgbe_aci_cmd_fw_log_cfg_resp fw_modules[IXGBE_ACI_FW_LOG_ID_MAX]; + struct ixgbe_aci_cmd_fw_log *cmd; + struct ixgbe_aci_desc desc; + s32 status; + u16 i; + + if (num_entries > IXGBE_ACI_FW_LOG_ID_MAX) + return IXGBE_ERR_PARAM; + + for (i = 0; i < num_entries; i++) { + fw_modules[i].module_identifier = + IXGBE_CPU_TO_LE16(entries[i].module_id); + fw_modules[i].log_level = entries[i].log_level; + } + + ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_fw_logs_config); + desc.flags |= IXGBE_CPU_TO_LE16(IXGBE_ACI_FLAG_RD); + + cmd = &desc.params.fw_log; + + cmd->cmd_flags = IXGBE_ACI_FW_LOG_CONF_SET_VALID; + cmd->ops.cfg.log_resolution = IXGBE_CPU_TO_LE16(log_resolution); + cmd->ops.cfg.mdl_cnt = IXGBE_CPU_TO_LE16(num_entries); + + if (options & IXGBE_FWLOG_OPTION_ARQ_ENA) + cmd->cmd_flags |= IXGBE_ACI_FW_LOG_CONF_AQ_EN; + if (options & IXGBE_FWLOG_OPTION_UART_ENA) + cmd->cmd_flags |= IXGBE_ACI_FW_LOG_CONF_UART_EN; + + status = ixgbe_aci_send_cmd(hw, &desc, fw_modules, + sizeof(*fw_modules) * num_entries); + + return status; +} + +/** + * ixgbe_fwlog_supported - Cached for whether FW supports FW logging or not + * @hw: pointer to the HW structure + * + * This will always return false if called before ixgbe_init_hw(), so it must be + * called after ixgbe_init_hw(). + * + * Return: true if FW supports FW logging. + * If this function is called before ixgbe_init_hw(), return false. + */ +bool ixgbe_fwlog_supported(struct ixgbe_hw *hw) +{ + return hw->fwlog_support_ena; +} + +/** + * ixgbe_fwlog_set - Set the firmware logging settings + * @hw: pointer to the HW structure + * @cfg: config used to set firmware logging + * + * Call this function whenever the driver needs to set the firmware + * logging configuration. It can be called on initialization, reset, or during + * runtime. + * + * If the PF wishes to receive FW logging then it must register via + * ixgbe_fwlog_register. Note, that ixgbe_fwlog_register does not need to + * be called for init. + * + * Return: the exit code of the operation. + */ +s32 ixgbe_fwlog_set(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg) +{ + s32 status; + + if (!ixgbe_fwlog_supported(hw)) + return IXGBE_ERR_NOT_SUPPORTED; + + if (!ixgbe_fwlog_valid_cfg(hw, cfg)) + return IXGBE_ERR_PARAM; + + status = ixgbe_aci_fwlog_set(hw, cfg->module_entries, + IXGBE_ACI_FW_LOG_ID_MAX, cfg->options, + cfg->log_resolution); + if (!status) + ixgbe_fwlog_cache_cfg(hw, cfg); + + return status; +} + +/** + * ixgbe_fwlog_update_cached_entries - Update module entries in cached + * FW logging config + * @hw: pointer to the HW structure + * @entries: entries to cache + * @num_entries: number of @entries + * + * Update module entries in cached FW logging config. + */ +static void ixgbe_fwlog_update_cached_entries(struct ixgbe_hw *hw, + struct ixgbe_fwlog_module_entry *entries, + u16 num_entries) +{ + u16 i; + + for (i = 0; i < num_entries; i++) { + struct ixgbe_fwlog_module_entry *updated = &entries[i]; + u16 j; + + for (j = 0; j < IXGBE_ACI_FW_LOG_ID_MAX; j++) { + struct ixgbe_fwlog_module_entry *cached = + &hw->fwlog_cfg.module_entries[j]; + + if (cached->module_id == updated->module_id) { + cached->log_level = updated->log_level; + break; + } + } + } +} + +/** + * ixgbe_fwlog_update_modules - Update the log level 1 or more + * FW logging modules + * @hw: pointer to the HW structure + * @entries: array of ixgbe_fwlog_module_entry(s) + * @num_entries: number of entries + * + * Update the log level of 1 or more FW logging modules via module ID. + * + * Only the entries passed in will be affected. All other firmware logging + * settings will be unaffected. + * + * Return: the exit code of the operation. + */ +s32 ixgbe_fwlog_update_modules(struct ixgbe_hw *hw, + struct ixgbe_fwlog_module_entry *entries, + u16 num_entries) +{ + struct ixgbe_fwlog_cfg cfg; + s32 status; + + if (!ixgbe_fwlog_supported(hw)) + return IXGBE_ERR_NOT_SUPPORTED; + + if (num_entries > IXGBE_ACI_FW_LOG_ID_MAX) + return IXGBE_ERR_PARAM; + + if (!ixgbe_fwlog_valid_module_entries(hw, entries, num_entries)) + return IXGBE_ERR_PARAM; + + status = ixgbe_fwlog_get(hw, &cfg); + if (status) + goto status_out; + + status = ixgbe_aci_fwlog_set(hw, entries, num_entries, cfg.options, + cfg.log_resolution); + if (!status) + ixgbe_fwlog_update_cached_entries(hw, entries, num_entries); + +status_out: + return status; +} + +/** + * ixgbe_aci_fwlog_register - Register PF for firmware logging events. + * @hw: pointer to the HW structure + * @reg: true to register and false to unregister + * + * Register a PF for firmware logging events using ACI command (0xFF31). + * + * Return: the exit code of the operation. + */ +static s32 ixgbe_aci_fwlog_register(struct ixgbe_hw *hw, bool reg) +{ + struct ixgbe_aci_desc desc; + + ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_fw_logs_register); + + if (reg) + desc.params.fw_log.cmd_flags = IXGBE_ACI_FW_LOG_AQ_REGISTER; + + return ixgbe_aci_send_cmd(hw, &desc, NULL, 0); +} + +/** + * ixgbe_fwlog_register - Register the PF for firmware logging + * @hw: pointer to the HW structure + * + * After this call the PF will start to receive firmware logging based on the + * configuration set in ixgbe_fwlog_set. + * + * Return: the exit code of the operation. + */ +s32 ixgbe_fwlog_register(struct ixgbe_hw *hw) +{ + s32 status; + + if (!ixgbe_fwlog_supported(hw)) + return IXGBE_ERR_NOT_SUPPORTED; + + status = ixgbe_aci_fwlog_register(hw, true); + + if (!status) + hw->fwlog_cfg.options |= IXGBE_FWLOG_OPTION_IS_REGISTERED; + + return status; +} + +/** + * ixgbe_fwlog_unregister - Unregister the PF from firmware logging + * @hw: pointer to the HW structure + * + * Make an attempt to unregister the PF from firmware logging. + * + * Return: the exit code of the operation. + */ +s32 ixgbe_fwlog_unregister(struct ixgbe_hw *hw) +{ + s32 status; + + if (!ixgbe_fwlog_supported(hw)) + return IXGBE_ERR_NOT_SUPPORTED; + + status = ixgbe_aci_fwlog_register(hw, false); + if (!status) + hw->fwlog_cfg.options &= ~IXGBE_FWLOG_OPTION_IS_REGISTERED; + + return status; +} + +/** + * ixgbe_aci_fwlog_get - Get the current firmware logging configuration + * @hw: pointer to the HW structure + * @cfg: firmware logging configuration to populate + * + * Make an attempt to get the current firmware logging + * configuration using ACI command (0xFF32). + * + * Return: the exit code of the operation. + */ +static s32 ixgbe_aci_fwlog_get(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg) +{ + struct ixgbe_aci_cmd_fw_log_cfg_resp *fw_modules; + struct ixgbe_aci_cmd_fw_log *cmd; + struct ixgbe_aci_desc desc; + u16 i, module_id_cnt; + u8 *buf = NULL; + s32 status; + + memset(cfg, 0, sizeof(*cfg)); + + ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_fw_logs_query); + cmd = &desc.params.fw_log; + + cmd->cmd_flags = IXGBE_ACI_FW_LOG_AQ_QUERY; + + buf = (u8 *)ixgbe_malloc(hw, IXGBE_ACI_MAX_BUFFER_SIZE); + if (!buf) + return IXGBE_ERR_OUT_OF_MEM; + + status = ixgbe_aci_send_cmd(hw, &desc, buf, IXGBE_ACI_MAX_BUFFER_SIZE); + if (status) { + goto status_out; + } + + module_id_cnt = IXGBE_LE16_TO_CPU(cmd->ops.cfg.mdl_cnt); + if (module_id_cnt > IXGBE_ACI_FW_LOG_ID_MAX) { + module_id_cnt = IXGBE_ACI_FW_LOG_ID_MAX; + } + + cfg->log_resolution = (u8)IXGBE_LE16_TO_CPU(cmd->ops.cfg.log_resolution); + if (cmd->cmd_flags & IXGBE_ACI_FW_LOG_CONF_AQ_EN) + cfg->options |= IXGBE_FWLOG_OPTION_ARQ_ENA; + if (cmd->cmd_flags & IXGBE_ACI_FW_LOG_CONF_UART_EN) + cfg->options |= IXGBE_FWLOG_OPTION_UART_ENA; + if (cmd->cmd_flags & IXGBE_ACI_FW_LOG_QUERY_REGISTERED) + cfg->options |= IXGBE_FWLOG_OPTION_IS_REGISTERED; + + fw_modules = (struct ixgbe_aci_cmd_fw_log_cfg_resp *)buf; + + for (i = 0; i < module_id_cnt; i++) { + struct ixgbe_aci_cmd_fw_log_cfg_resp *fw_module = &fw_modules[i]; + + cfg->module_entries[i].module_id = + IXGBE_LE16_TO_CPU(fw_module->module_identifier); + cfg->module_entries[i].log_level = fw_module->log_level; + } + +status_out: + if (buf) + ixgbe_free(hw, buf); + return status; +} + +/** + * ixgbe_fwlog_set_support_ena - Set if FW logging is supported by FW + * @hw: pointer to the HW struct + * + * If FW returns success to the ixgbe_aci_fwlog_get call then it supports FW + * logging, else it doesn't. Set the fwlog_support_ena flag accordingly. + * + * This function is only meant to be called during driver init to determine if + * the FW support FW logging. + * + * Return: the exit code of the operation. + */ +void ixgbe_fwlog_set_support_ena(struct ixgbe_hw *hw) +{ + struct ixgbe_fwlog_cfg cfg; + s32 status; + + hw->fwlog_support_ena = false; + + /* don't call ixgbe_fwlog_get() because that would overwrite the cached + * configuration from the call to ixgbe_fwlog_init(), which is expected + * to be called prior to this function + */ + status = ixgbe_aci_fwlog_get(hw, &cfg); + if (!status) + hw->fwlog_support_ena = true; +} + +/** + * ixgbe_fwlog_get - Get the firmware logging settings + * @hw: pointer to the HW structure + * @cfg: config to populate based on current firmware logging settings + * + * Get the current firmware logging settings. + * + * Return: the exit code of the operation. + */ +s32 ixgbe_fwlog_get(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg) +{ + s32 status; + + if (!ixgbe_fwlog_supported(hw)) + return IXGBE_ERR_NOT_SUPPORTED; + + if (!cfg) + return IXGBE_ERR_PARAM; + + status = ixgbe_aci_fwlog_get(hw, cfg); + if (status) + return status; + + ixgbe_fwlog_cache_cfg(hw, cfg); + + return IXGBE_SUCCESS; +} + +/** + * ixgbe_fwlog_event_dump - Dump the event received over the Admin Receive Queue + * @hw: pointer to the HW structure + * @desc: Admin Receive Queue descriptor + * @buf: buffer that contains the FW log event data + * + * If the driver receives the ixgbe_aci_opc_fw_logs_event on the Admin Receive + * Queue, then it should call this function to dump the FW log data. + */ +void ixgbe_fwlog_event_dump(struct ixgbe_hw *hw, + struct ixgbe_aci_desc *desc, void *buf) +{ + if (!ixgbe_fwlog_supported(hw)) + return; + + ixgbe_info_fwlog(hw, 32, 1, (u8 *)buf, + IXGBE_LE16_TO_CPU(desc->datalen)); +} + +/** * ixgbe_aci_set_health_status_config - Configure FW health events * @hw: pointer to the HW struct * @event_source: type of diagnostic events to enable @@ -3883,9 +4387,14 @@ s32 ixgbe_init_ops_E610(struct ixgbe_hw *hw) /* PHY */ phy->ops.init = ixgbe_init_phy_ops_E610; phy->ops.identify = ixgbe_identify_phy_E610; - phy->eee_speeds_supported = IXGBE_LINK_SPEED_10_FULL | - IXGBE_LINK_SPEED_100_FULL | - IXGBE_LINK_SPEED_1GB_FULL; + + if (hw->device_id == IXGBE_DEV_ID_E610_2_5G_T) + phy->eee_speeds_supported = IXGBE_LINK_SPEED_2_5GB_FULL; + else + phy->eee_speeds_supported = IXGBE_LINK_SPEED_2_5GB_FULL | + IXGBE_LINK_SPEED_5GB_FULL | + IXGBE_LINK_SPEED_10GB_FULL; + phy->eee_speeds_advertised = phy->eee_speeds_supported; /* Additional ops overrides for e610 to go here */ @@ -4513,19 +5022,18 @@ s32 ixgbe_setup_eee_E610(struct ixgbe_hw *hw, bool enable_eee) phy_cfg.caps |= IXGBE_ACI_PHY_ENA_LINK; phy_cfg.caps |= IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT; + /* setup only speeds which are defined for [0x0601/0x0600].eee_cap */ if (enable_eee) { - if (phy_caps.phy_type_low & IXGBE_PHY_TYPE_LOW_100BASE_TX) + if (hw->phy.eee_speeds_advertised & IXGBE_LINK_SPEED_100_FULL) eee_cap |= IXGBE_ACI_PHY_EEE_EN_100BASE_TX; - if (phy_caps.phy_type_low & IXGBE_PHY_TYPE_LOW_1000BASE_T) + if (hw->phy.eee_speeds_advertised & IXGBE_LINK_SPEED_1GB_FULL) eee_cap |= IXGBE_ACI_PHY_EEE_EN_1000BASE_T; - if (phy_caps.phy_type_low & IXGBE_PHY_TYPE_LOW_1000BASE_KX) - eee_cap |= IXGBE_ACI_PHY_EEE_EN_1000BASE_KX; - if (phy_caps.phy_type_low & IXGBE_PHY_TYPE_LOW_10GBASE_T) + if (hw->phy.eee_speeds_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) + eee_cap |= IXGBE_ACI_PHY_EEE_EN_2_5GBASE_T; + if (hw->phy.eee_speeds_advertised & IXGBE_LINK_SPEED_5GB_FULL) + eee_cap |= IXGBE_ACI_PHY_EEE_EN_5GBASE_T; + if (hw->phy.eee_speeds_advertised & IXGBE_LINK_SPEED_10GB_FULL) eee_cap |= IXGBE_ACI_PHY_EEE_EN_10GBASE_T; - if (phy_caps.phy_type_low & IXGBE_PHY_TYPE_LOW_10GBASE_KR_CR1) - eee_cap |= IXGBE_ACI_PHY_EEE_EN_10GBASE_KR; - if (phy_caps.phy_type_high & IXGBE_PHY_TYPE_HIGH_10BASE_T) - eee_cap |= IXGBE_ACI_PHY_EEE_EN_10BASE_T; } /* Set EEE capability for particular PHY types */ diff --git a/sys/dev/ixgbe/ixgbe_e610.h b/sys/dev/ixgbe/ixgbe_e610.h index 94e600139499..7af5506d85e8 100644 --- a/sys/dev/ixgbe/ixgbe_e610.h +++ b/sys/dev/ixgbe/ixgbe_e610.h @@ -169,6 +169,19 @@ s32 ixgbe_handle_nvm_access(struct ixgbe_hw *hw, s32 ixgbe_aci_set_health_status_config(struct ixgbe_hw *hw, u8 event_source); +s32 ixgbe_fwlog_init(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg); +bool ixgbe_fwlog_supported(struct ixgbe_hw *hw); +s32 ixgbe_fwlog_set(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg); +s32 ixgbe_fwlog_update_modules(struct ixgbe_hw *hw, + struct ixgbe_fwlog_module_entry *entries, + u16 num_entries); +s32 ixgbe_fwlog_register(struct ixgbe_hw *hw); +s32 ixgbe_fwlog_unregister(struct ixgbe_hw *hw); +void ixgbe_fwlog_set_support_ena(struct ixgbe_hw *hw); +s32 ixgbe_fwlog_get(struct ixgbe_hw *hw, struct ixgbe_fwlog_cfg *cfg); +void ixgbe_fwlog_event_dump(struct ixgbe_hw *hw, + struct ixgbe_aci_desc *desc, void *buf); + /* E610 operations */ s32 ixgbe_init_ops_E610(struct ixgbe_hw *hw); s32 ixgbe_reset_hw_E610(struct ixgbe_hw *hw); diff --git a/sys/dev/ixgbe/ixgbe_features.h b/sys/dev/ixgbe/ixgbe_features.h index bee9040319d8..bbc7507b29ac 100644 --- a/sys/dev/ixgbe/ixgbe_features.h +++ b/sys/dev/ixgbe/ixgbe_features.h @@ -58,6 +58,7 @@ #define IXGBE_FEATURE_NEEDS_CTXD (u32)(1 << 13) #define IXGBE_FEATURE_RECOVERY_MODE (u32)(1 << 15) #define IXGBE_FEATURE_DBG_DUMP (u32)(1 << 16) +#define IXGBE_FEATURE_FW_LOGGING (u32)(1 << 17) /* Check for OS support. Undefine features if not included in the OS */ #ifndef PCI_IOV diff --git a/sys/dev/ixgbe/ixgbe_fw_logging.c b/sys/dev/ixgbe/ixgbe_fw_logging.c new file mode 100644 index 000000000000..6202d504423f --- /dev/null +++ b/sys/dev/ixgbe/ixgbe_fw_logging.c @@ -0,0 +1,467 @@ +/** + * @file ixgbe_fw_logging.c + * @brief firmware logging sysctls + * + * Contains sysctls to enable and configure firmware logging debug support. + */ + + #include "ixgbe.h" + + /** + * ixgbe_reconfig_fw_log - Re-program firmware logging configuration + * @sc: private softc structure + * @cfg: firmware log configuration to latch + * + * If the adminq is currently active, ask firmware to update the logging + * configuration. If the adminq is currently down, then do nothing. In this + * case, ixgbe_init_hw() will re-configure firmware logging as soon as it brings + * up the adminq. + */ + static int + ixgbe_reconfig_fw_log(struct ixgbe_softc *sc, struct ixgbe_fwlog_cfg *cfg) + { + int status; + + ixgbe_fwlog_init(&sc->hw, cfg); + + if (!ixgbe_fwlog_supported(&sc->hw)) + return (0); + + status = ixgbe_fwlog_set(&sc->hw, cfg); + if (status != IXGBE_SUCCESS) { + DEBUGOUT1("Failed to reconfigure firmware logging, status %d\n", + status); + return (ENODEV); + } + + return (0); + } + + /** + * ixgbe_sysctl_fwlog_set_cfg_options - Sysctl for setting fwlog cfg options + * @oidp: sysctl oid structure + * @arg1: private softc structure + * @arg2: option to adjust + * @req: sysctl request pointer + * + * On read: displays whether firmware logging was reported during attachment + * On write: enables/disables firmware logging during attach phase + * + * This has no effect on the legacy (V1) version of firmware logging. + */ + static int + ixgbe_sysctl_fwlog_set_cfg_options(SYSCTL_HANDLER_ARGS) + { + struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; + struct ixgbe_fwlog_cfg *cfg = &sc->hw.fwlog_cfg; + int error; + u16 option = (u16)arg2; + bool enabled; + + enabled = !!(cfg->options & option); + + error = sysctl_handle_bool(oidp, &enabled, 0, req); + if ((error) || (req->newptr == NULL)) + return (error); + + if (enabled) + cfg->options |= option; + else + cfg->options &= ~option; + + return ixgbe_reconfig_fw_log(sc, cfg); + } + + /** + * ixgbe_sysctl_fwlog_log_resolution - Sysctl for setting log message resolution + * @oidp: sysctl oid structure + * @arg1: private softc structure + * @arg2: __unused__ + * @req: sysctl request pointer + * + * On read: displays message queue limit before posting + * On write: sets message queue limit before posting + * + * This has no effect on the legacy (V1) version of firmware logging. + */ + static int + ixgbe_sysctl_fwlog_log_resolution(SYSCTL_HANDLER_ARGS) + { + struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; + struct ixgbe_fwlog_cfg *cfg = &sc->hw.fwlog_cfg; + int error; + u8 resolution; + + UNREFERENCED_PARAMETER(arg2); + + resolution = cfg->log_resolution; + + error = sysctl_handle_8(oidp, &resolution, 0, req); + if ((error) || (req->newptr == NULL)) + return (error); + + if ((resolution < IXGBE_ACI_FW_LOG_MIN_RESOLUTION) || + (resolution > IXGBE_ACI_FW_LOG_MAX_RESOLUTION)) { + DEBUGOUT("Log resolution out-of-bounds\n"); + return (EINVAL); + } + + cfg->log_resolution = resolution; + + return ixgbe_reconfig_fw_log(sc, cfg); + } + + /** + * ixgbe_sysctl_fwlog_register - Sysctl for (de)registering firmware logs + * @oidp: sysctl oid structure + * @arg1: private softc structure + * @arg2: __unused__ + * @req: sysctl request pointer + * + * On read: displays whether firmware logging is registered + * On write: (de)registers firmware logging. + */ + static int + ixgbe_sysctl_fwlog_register(SYSCTL_HANDLER_ARGS) + { + struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; + struct ixgbe_fwlog_cfg *cfg = &sc->hw.fwlog_cfg; + int status; + int error; + u8 enabled; + + UNREFERENCED_PARAMETER(arg2); + + if (cfg->options & IXGBE_FWLOG_OPTION_IS_REGISTERED) + enabled = true; + else + enabled = false; + + error = sysctl_handle_bool(oidp, &enabled, 0, req); + if ((error) || (req->newptr == NULL)) + return (error); + + if (enabled) { + status = ixgbe_fwlog_register(&sc->hw); + if (status == IXGBE_SUCCESS) + sc->feat_en |= IXGBE_FEATURE_FW_LOGGING; + } else { + status = ixgbe_fwlog_unregister(&sc->hw); + if (status == IXGBE_SUCCESS) + sc->feat_en &= ~IXGBE_FEATURE_FW_LOGGING; + } + + if (status != IXGBE_SUCCESS) + return (EIO); + + return (0); + } + + /** + * ixgbe_log_sev_str - Convert log level to a string + * @log_level: the log level to convert + * + * Convert the u8 log level of a FW logging module into a readable + * string for outputting in a sysctl. + */ + struct ixgbe_str_buf { + char str[IXGBE_STR_BUF_LEN]; + }; + + static struct ixgbe_str_buf + _ixgbe_log_sev_str(u8 log_level) + { + struct ixgbe_str_buf buf = { .str = "" }; + const char *str = NULL; + + switch (log_level) { + case IXGBE_FWLOG_LEVEL_NONE: + str = "none"; + break; + case IXGBE_FWLOG_LEVEL_ERROR: + str = "error"; + break; + case IXGBE_FWLOG_LEVEL_WARNING: + str = "warning"; + break; + case IXGBE_FWLOG_LEVEL_NORMAL: + str = "normal"; + break; + case IXGBE_FWLOG_LEVEL_VERBOSE: + str = "verbose"; + break; + default: + break; + } + + if (str) + snprintf(buf.str, IXGBE_STR_BUF_LEN, "%s", str); + else + snprintf(buf.str, IXGBE_STR_BUF_LEN, "%u", log_level); + + return buf; + } + + #define ixgbe_log_sev_str(log_level) _ixgbe_log_sev_str(log_level).str + + /** + * ixgbe_sysctl_fwlog_module_log_severity - Add tunables for a FW logging module + * @oidp: sysctl oid structure + * @arg1: private softc structure + * @arg2: index to logging module + * @req: sysctl request pointer + */ + static int + ixgbe_sysctl_fwlog_module_log_severity(SYSCTL_HANDLER_ARGS) + { + struct ixgbe_softc *sc = (struct ixgbe_softc *)arg1; + struct ixgbe_fwlog_cfg *cfg = &sc->hw.fwlog_cfg; + struct sbuf *sbuf; + char *sev_str_end; + enum ixgbe_aci_fw_logging_mod module = (enum ixgbe_aci_fw_logging_mod)arg2; + int error, ll_num; + u8 log_level; + char sev_str[16]; + bool sev_set = false; + + log_level = cfg->module_entries[module].log_level; + sbuf = sbuf_new(NULL, sev_str, sizeof(sev_str), SBUF_FIXEDLEN); + sbuf_printf(sbuf, "%d<%s>", log_level, ixgbe_log_sev_str(log_level)); + sbuf_finish(sbuf); + sbuf_delete(sbuf); + + error = sysctl_handle_string(oidp, sev_str, sizeof(sev_str), req); + if ((error) || (req->newptr == NULL)) + return (error); + + if (strcasecmp(ixgbe_log_sev_str(IXGBE_FWLOG_LEVEL_VERBOSE), sev_str) == 0) { + log_level = IXGBE_FWLOG_LEVEL_VERBOSE; + sev_set = true; + } else if (strcasecmp(ixgbe_log_sev_str(IXGBE_FWLOG_LEVEL_NORMAL), sev_str) == 0) { + log_level = IXGBE_FWLOG_LEVEL_NORMAL; + sev_set = true; + } else if (strcasecmp(ixgbe_log_sev_str(IXGBE_FWLOG_LEVEL_WARNING), sev_str) == 0) { + log_level = IXGBE_FWLOG_LEVEL_WARNING; + sev_set = true; + } else if (strcasecmp(ixgbe_log_sev_str(IXGBE_FWLOG_LEVEL_ERROR), sev_str) == 0) { + log_level = IXGBE_FWLOG_LEVEL_ERROR; + sev_set = true; + } else if (strcasecmp(ixgbe_log_sev_str(IXGBE_FWLOG_LEVEL_NONE), sev_str) == 0) { + log_level = IXGBE_FWLOG_LEVEL_NONE; + sev_set = true; + } + + if (!sev_set) { + ll_num = strtol(sev_str, &sev_str_end, 0); + if (sev_str_end == sev_str) + ll_num = -1; + if ((ll_num >= IXGBE_FWLOG_LEVEL_NONE) && + (ll_num < IXGBE_FWLOG_LEVEL_INVALID)) + log_level = ll_num; + else { + DEBUGOUT2("%s: \"%s\" is not a valid log level\n", + __func__, sev_str); + return (EINVAL); + } + } + + cfg->module_entries[module].log_level = log_level; + + return ixgbe_reconfig_fw_log(sc, cfg); + } + + #define IXGBE_SYSCTL_HELP_FWLOG_LOG_RESOLUTION \ + "\nControl firmware message limit to send per ARQ event" \ + "\t\nMin: 1" \ + "\t\nMax: 128" + + #define IXGBE_SYSCTL_HELP_FWLOG_ARQ_ENA \ + "\nControl whether to enable/disable reporting to admin Rx queue" \ + "\n1 - Enable firmware reporting via ARQ" \ + "\n0 - Disable firmware reporting via ARQ" + + #define IXGBE_SYSCTL_HELP_FWLOG_UART_ENA \ + "\nControl whether to enable/disable reporting to UART" \ + "\n1 - Enable firmware reporting via UART" \ + "\n0 - Disable firmware reporting via UART" + + #define IXGBE_SYSCTL_HELP_FWLOG_ENABLE_ON_LOAD \ + "\nControl whether to enable logging during the attach phase" \ + "\n1 - Enable firmware logging during attach phase" \ + "\n0 - Disable firmware logging during attach phase" + + #define IXGBE_SYSCTL_HELP_FWLOG_REGISTER \ + "\nControl whether to enable/disable firmware logging" \ + "\n1 - Enable firmware logging" \ + "\n0 - Disable firmware logging" + + #define IXGBE_SYSCTL_HELP_FWLOG_MODULE_SEVERITY \ + "\nControl the level of log output messages for this module" \ + "\n\tverbose <4> - Verbose messages + (Error|Warning|Normal)" \ + "\n\tnormal <3> - Normal messages + (Error|Warning)" \ + "\n\twarning <2> - Warning messages + (Error)" \ + "\n\terror <1> - Error messages" \ + "\n\tnone <0> - Disables all logging for this module" + + /** + * ixgbe_fw_module_str - Convert a FW logging module to a string name + * @module: the module to convert + * + * Given a FW logging module id, convert it to a shorthand human readable + * name, for generating sysctl tunables. + */ + static const char * + ixgbe_fw_module_str(enum ixgbe_aci_fw_logging_mod module) + { + switch (module) { + case IXGBE_ACI_FW_LOG_ID_GENERAL: + return "general"; + case IXGBE_ACI_FW_LOG_ID_CTRL: + return "ctrl"; + case IXGBE_ACI_FW_LOG_ID_LINK: + return "link"; + case IXGBE_ACI_FW_LOG_ID_LINK_TOPO: + return "link_topo"; + case IXGBE_ACI_FW_LOG_ID_DNL: + return "dnl"; + case IXGBE_ACI_FW_LOG_ID_I2C: + return "i2c"; + case IXGBE_ACI_FW_LOG_ID_SDP: + return "sdp"; + case IXGBE_ACI_FW_LOG_ID_MDIO: + return "mdio"; + case IXGBE_ACI_FW_LOG_ID_ADMINQ: + return "adminq"; + case IXGBE_ACI_FW_LOG_ID_HDMA: + return "hdma"; + case IXGBE_ACI_FW_LOG_ID_LLDP: + return "lldp"; + case IXGBE_ACI_FW_LOG_ID_DCBX: + return "dcbx"; + case IXGBE_ACI_FW_LOG_ID_DCB: + return "dcb"; + case IXGBE_ACI_FW_LOG_ID_XLR: + return "xlr"; + case IXGBE_ACI_FW_LOG_ID_NVM: + return "nvm"; + case IXGBE_ACI_FW_LOG_ID_AUTH: + return "auth"; + case IXGBE_ACI_FW_LOG_ID_VPD: + return "vpd"; + case IXGBE_ACI_FW_LOG_ID_IOSF: + return "iosf"; + case IXGBE_ACI_FW_LOG_ID_PARSER: + return "parser"; + case IXGBE_ACI_FW_LOG_ID_SW: + return "sw"; + case IXGBE_ACI_FW_LOG_ID_SCHEDULER: + return "scheduler"; + case IXGBE_ACI_FW_LOG_ID_TXQ: + return "txq"; + case IXGBE_ACI_FW_LOG_ID_ACL: + return "acl"; + case IXGBE_ACI_FW_LOG_ID_POST: + return "post"; + case IXGBE_ACI_FW_LOG_ID_WATCHDOG: + return "watchdog"; + case IXGBE_ACI_FW_LOG_ID_TASK_DISPATCH: + return "task_dispatch"; + case IXGBE_ACI_FW_LOG_ID_MNG: + return "mng"; + case IXGBE_ACI_FW_LOG_ID_SYNCE: + return "synce"; + case IXGBE_ACI_FW_LOG_ID_HEALTH: + return "health"; + case IXGBE_ACI_FW_LOG_ID_TSDRV: + return "tsdrv"; + case IXGBE_ACI_FW_LOG_ID_PFREG: + return "pfreg"; + case IXGBE_ACI_FW_LOG_ID_MDLVER: + return "mdlver"; + case IXGBE_ACI_FW_LOG_ID_MAX: + return "unknown"; + } + + /* The compiler generates errors on unhandled enum values if we omit + * the default case. + */ + return "unknown"; + } + + /** + * ixgbe_add_fw_logging_tunables - Add tunables to configure FW logging events + * @sc: private softc structure + * @parent: parent node to add the tunables under + * + * Add tunables for configuring the firmware logging support. This includes + * a control to enable the logging, and controls for each module to configure + * which events to receive. + */ + void + ixgbe_add_fw_logging_tunables(struct ixgbe_softc *sc, struct sysctl_oid *parent) + { + struct sysctl_oid_list *parent_list, *fwlog_list, *module_list; + struct sysctl_oid *fwlog_node, *module_node; + struct sysctl_ctx_list *ctx; + struct ixgbe_hw *hw = &sc->hw; + struct ixgbe_fwlog_cfg *cfg; + device_t dev = sc->dev; + enum ixgbe_aci_fw_logging_mod module; + u16 i; + + cfg = &hw->fwlog_cfg; + ctx = device_get_sysctl_ctx(dev); + parent_list = SYSCTL_CHILDREN(parent); + + fwlog_node = SYSCTL_ADD_NODE(ctx, parent_list, OID_AUTO, "fw_log", + CTLFLAG_RD, NULL, + "Firmware Logging"); + fwlog_list = SYSCTL_CHILDREN(fwlog_node); + + cfg->log_resolution = 10; + SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "log_resolution", + CTLTYPE_U8 | CTLFLAG_RWTUN, sc, + 0, ixgbe_sysctl_fwlog_log_resolution, + "CU", IXGBE_SYSCTL_HELP_FWLOG_LOG_RESOLUTION); + + cfg->options |= IXGBE_FWLOG_OPTION_ARQ_ENA; + SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "arq_en", + CTLTYPE_U8 | CTLFLAG_RWTUN, sc, + IXGBE_FWLOG_OPTION_ARQ_ENA, ixgbe_sysctl_fwlog_set_cfg_options, + "CU", IXGBE_SYSCTL_HELP_FWLOG_ARQ_ENA); + + SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "uart_en", + CTLTYPE_U8 | CTLFLAG_RWTUN, sc, + IXGBE_FWLOG_OPTION_UART_ENA, ixgbe_sysctl_fwlog_set_cfg_options, + "CU", IXGBE_SYSCTL_HELP_FWLOG_UART_ENA); + + SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "on_load", + CTLTYPE_U8 | CTLFLAG_RWTUN, sc, + IXGBE_FWLOG_OPTION_REGISTER_ON_INIT, ixgbe_sysctl_fwlog_set_cfg_options, + "CU", IXGBE_SYSCTL_HELP_FWLOG_ENABLE_ON_LOAD); + + SYSCTL_ADD_PROC(ctx, fwlog_list, OID_AUTO, "register", + CTLTYPE_U8 | CTLFLAG_RWTUN, sc, + 0, ixgbe_sysctl_fwlog_register, + "CU", IXGBE_SYSCTL_HELP_FWLOG_REGISTER); + + module_node = SYSCTL_ADD_NODE(ctx, fwlog_list, OID_AUTO, "severity", + CTLFLAG_RD, NULL, + "Level of log output"); + + module_list = SYSCTL_CHILDREN(module_node); + + for (i = 0; i < IXGBE_ACI_FW_LOG_ID_MAX; i++) { + /* Setup some defaults */ + cfg->module_entries[i].module_id = i; + cfg->module_entries[i].log_level = IXGBE_FWLOG_LEVEL_NONE; + module = (enum ixgbe_aci_fw_logging_mod)i; + + SYSCTL_ADD_PROC(ctx, module_list, + OID_AUTO, ixgbe_fw_module_str(module), + CTLTYPE_STRING | CTLFLAG_RWTUN, sc, + module, ixgbe_sysctl_fwlog_module_log_severity, + "A", IXGBE_SYSCTL_HELP_FWLOG_MODULE_SEVERITY); + } + } +
\ No newline at end of file diff --git a/sys/dev/ixgbe/ixgbe_osdep.c b/sys/dev/ixgbe/ixgbe_osdep.c index 9bd9ce63b786..d96e15f4f87f 100644 --- a/sys/dev/ixgbe/ixgbe_osdep.c +++ b/sys/dev/ixgbe/ixgbe_osdep.c @@ -140,3 +140,39 @@ ixgbe_destroy_lock(struct ixgbe_lock *lock) if (mtx_initialized(&lock->mutex)) mtx_destroy(&lock->mutex); } + +/** + * ixgbe_info_fwlog - Format and print an array of values to the console + * @hw: private hardware structure + * @rowsize: preferred number of rows to use + * @groupsize: preferred size in bytes to print each chunk + * @buf: the array buffer to print + * @len: size of the array buffer + * + * Format the given array as a series of uint8_t values with hexadecimal + * notation and log the contents to the console log. This variation is + * specific to firmware logging. + * + * TODO: Currently only supports a group size of 1, due to the way hexdump is + * implemented. + */ +void +ixgbe_info_fwlog(struct ixgbe_hw *hw, uint32_t rowsize, uint32_t __unused groupsize, + uint8_t *buf, size_t len) +{ + device_t dev = ((struct ixgbe_softc *)hw->back)->dev; + char prettyname[20]; + + if (!ixgbe_fwlog_supported(hw)) + return; + + /* Format the device header to a string */ + snprintf(prettyname, sizeof(prettyname), "%s: FWLOG: ", + device_get_nameunit(dev)); + + /* Make sure the row-size isn't too large */ + if (rowsize > 0xFF) + rowsize = 0xFF; + + hexdump(buf, len, prettyname, HD_OMIT_CHARS | rowsize); +} diff --git a/sys/dev/ixgbe/ixgbe_osdep.h b/sys/dev/ixgbe/ixgbe_osdep.h index 8cf1d13736ce..ec2b3274ec31 100644 --- a/sys/dev/ixgbe/ixgbe_osdep.h +++ b/sys/dev/ixgbe/ixgbe_osdep.h @@ -253,4 +253,7 @@ ixgbe_free(struct ixgbe_hw __unused *hw, void *addr) free(addr, M_DEVBUF); } +void ixgbe_info_fwlog(struct ixgbe_hw *hw, uint32_t rowsize, + uint32_t groupsize, uint8_t *buf, size_t len); + #endif /* _IXGBE_OSDEP_H_ */ diff --git a/sys/dev/ixgbe/ixgbe_sriov.h b/sys/dev/ixgbe/ixgbe_sriov.h index e5a78a7220cc..3c456ee819f2 100644 --- a/sys/dev/ixgbe/ixgbe_sriov.h +++ b/sys/dev/ixgbe/ixgbe_sriov.h @@ -94,7 +94,7 @@ u32 ixgbe_get_mrqc(int); #define ixgbe_align_all_queue_indices(_a) #define ixgbe_vf_que_index(_a, _b, _c) (_c) #define ixgbe_get_mtqc(_a) IXGBE_MTQC_64Q_1PB -#define ixgbe_get_mrqc(_a) 0 +#define ixgbe_get_mrqc(_a) IXGBE_MRQC_RSSEN #endif /* PCI_IOV */ diff --git a/sys/dev/ixgbe/ixgbe_type_e610.h b/sys/dev/ixgbe/ixgbe_type_e610.h index e300030c3ba4..da46e503f660 100644 --- a/sys/dev/ixgbe/ixgbe_type_e610.h +++ b/sys/dev/ixgbe/ixgbe_type_e610.h @@ -721,6 +721,7 @@ struct ixgbe_aci_cmd_list_caps_elem { #define IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG3 0x0084 #define IXGBE_ACI_CAPS_OROM_RECOVERY_UPDATE 0x0090 #define IXGBE_ACI_CAPS_NEXT_CLUSTER_ID 0x0096 +#define IXGBE_ACI_CAPS_EEE 0x009B u8 major_ver; u8 minor_ver; /* Number of resources described by this capability */ @@ -836,10 +837,8 @@ struct ixgbe_aci_cmd_get_phy_caps_data { #define IXGBE_ACI_PHY_EEE_EN_100BASE_TX BIT(0) #define IXGBE_ACI_PHY_EEE_EN_1000BASE_T BIT(1) #define IXGBE_ACI_PHY_EEE_EN_10GBASE_T BIT(2) -#define IXGBE_ACI_PHY_EEE_EN_1000BASE_KX BIT(3) -#define IXGBE_ACI_PHY_EEE_EN_10GBASE_KR BIT(4) -#define IXGBE_ACI_PHY_EEE_EN_25GBASE_KR BIT(5) -#define IXGBE_ACI_PHY_EEE_EN_10BASE_T BIT(11) +#define IXGBE_ACI_PHY_EEE_EN_5GBASE_T BIT(11) +#define IXGBE_ACI_PHY_EEE_EN_2_5GBASE_T BIT(12) __le16 eeer_value; u8 phy_id_oui[4]; /* PHY/Module ID connected on the port */ u8 phy_fw_ver[8]; @@ -869,7 +868,9 @@ struct ixgbe_aci_cmd_get_phy_caps_data { #define IXGBE_ACI_MOD_TYPE_BYTE2_SFP_PLUS 0xA0 #define IXGBE_ACI_MOD_TYPE_BYTE2_QSFP_PLUS 0x86 u8 qualified_module_count; - u8 rsvd2[7]; /* Bytes 47:41 reserved */ + u8 rsvd2; + __le16 eee_entry_delay; + u8 rsvd3[4]; #define IXGBE_ACI_QUAL_MOD_COUNT_MAX 16 struct { u8 v_oui[3]; @@ -893,11 +894,38 @@ struct ixgbe_aci_cmd_set_phy_cfg { IXGBE_CHECK_PARAM_LEN(ixgbe_aci_cmd_set_phy_cfg); +/* Set PHY config obsolete command data structure (<FW 1.40) */ +struct ixgbe_aci_cmd_set_phy_cfg_data_pre_1_40 { + __le64 phy_type_low; /* Use values from IXGBE_PHY_TYPE_LOW_* */ + __le64 phy_type_high; /* Use values from IXGBE_PHY_TYPE_HIGH_* */ + u8 caps; + u8 low_power_ctrl_an; + __le16 eee_cap; /* Value from ixgbe_aci_get_phy_caps */ + __le16 eeer_value; /* Use defines from ixgbe_aci_get_phy_caps */ + u8 link_fec_opt; /* Use defines from ixgbe_aci_get_phy_caps */ + u8 module_compliance_enforcement; +}; + +IXGBE_CHECK_STRUCT_LEN(24, ixgbe_aci_cmd_set_phy_cfg_data_pre_1_40); + +#pragma pack(1) /* Set PHY config command data structure */ struct ixgbe_aci_cmd_set_phy_cfg_data { __le64 phy_type_low; /* Use values from IXGBE_PHY_TYPE_LOW_* */ __le64 phy_type_high; /* Use values from IXGBE_PHY_TYPE_HIGH_* */ u8 caps; + u8 low_power_ctrl_an; + __le16 eee_cap; /* Value from ixgbe_aci_get_phy_caps */ + __le16 eeer_value; /* Use defines from ixgbe_aci_get_phy_caps */ + u8 link_fec_opt; /* Use defines from ixgbe_aci_get_phy_caps */ + u8 module_compliance_enforcement; + __le16 eee_entry_delay; +}; + +IXGBE_CHECK_STRUCT_LEN(26, ixgbe_aci_cmd_set_phy_cfg_data); +#pragma pack() + +/* Set PHY config capabilities (@caps) defines */ #define IXGBE_ACI_PHY_ENA_VALID_MASK MAKEMASK(0xef, 0) #define IXGBE_ACI_PHY_ENA_TX_PAUSE_ABILITY BIT(0) #define IXGBE_ACI_PHY_ENA_RX_PAUSE_ABILITY BIT(1) @@ -906,14 +934,7 @@ struct ixgbe_aci_cmd_set_phy_cfg_data { #define IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT BIT(5) #define IXGBE_ACI_PHY_ENA_LESM BIT(6) #define IXGBE_ACI_PHY_ENA_AUTO_FEC BIT(7) - u8 low_power_ctrl_an; - __le16 eee_cap; /* Value from ixgbe_aci_get_phy_caps */ - __le16 eeer_value; /* Use defines from ixgbe_aci_get_phy_caps */ - u8 link_fec_opt; /* Use defines from ixgbe_aci_get_phy_caps */ - u8 module_compliance_enforcement; -}; -IXGBE_CHECK_STRUCT_LEN(24, ixgbe_aci_cmd_set_phy_cfg_data); /* Restart AN command data structure (direct 0x0605) * Also used for response, with only the lport_num field present. @@ -1035,8 +1056,9 @@ struct ixgbe_aci_cmd_get_link_status_data { #define IXGBE_ACI_LINK_SPEED_200GB BIT(11) #define IXGBE_ACI_LINK_SPEED_UNKNOWN BIT(15) __le16 reserved3; /* Aligns next field to 8-byte boundary */ - u8 ext_fec_status; -#define IXGBE_ACI_LINK_RS_272_FEC_EN BIT(0) /* RS 272 FEC enabled */ + u8 eee_status; +#define IXGBE_ACI_LINK_EEE_ENABLED BIT(2) +#define IXGBE_ACI_LINK_EEE_ACTIVE BIT(3) u8 reserved4; __le64 phy_type_low; /* Use values from IXGBE_PHY_TYPE_LOW_* */ __le64 phy_type_high; /* Use values from IXGBE_PHY_TYPE_HIGH_* */ @@ -2034,6 +2056,7 @@ struct ixgbe_link_status { * ixgbe_aci_get_phy_caps structure */ u8 module_type[IXGBE_ACI_MODULE_TYPE_TOTAL_BYTE]; + u8 eee_status; }; /* Common HW capabilities for SW use */ @@ -2112,6 +2135,12 @@ struct ixgbe_hw_common_caps { u8 apm_wol_support; u8 acpi_prog_mthd; u8 proxy_support; + u8 eee_support; +#define IXGBE_EEE_SUPPORT_100BASE_TX BIT(0) +#define IXGBE_EEE_SUPPORT_1000BASE_T BIT(1) +#define IXGBE_EEE_SUPPORT_10GBASE_T BIT(2) +#define IXGBE_EEE_SUPPORT_5GBASE_T BIT(3) +#define IXGBE_EEE_SUPPORT_2_5GBASE_T BIT(4) bool sec_rev_disabled; bool update_disabled; bool nvm_unified_update; diff --git a/sys/dev/ixgbe/ixgbe_x540.c b/sys/dev/ixgbe/ixgbe_x540.c index 57cec5b52e18..561fe6f0f78a 100644 --- a/sys/dev/ixgbe/ixgbe_x540.c +++ b/sys/dev/ixgbe/ixgbe_x540.c @@ -878,7 +878,21 @@ void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask) IXGBE_WRITE_REG(hw, IXGBE_SWFW_SYNC_BY_MAC(hw), swfw_sync); ixgbe_release_swfw_sync_semaphore(hw); - msec_delay(2); + + /* + * EEPROM / flash access requires a 2ms sleep or interacting with + * them isn't stable. However, a 2ms delay for all sync operations + * is very expensive for MDIO access. + * + * So use a 10us delay for PHY0/PHY1 MDIO and management access and + * 2ms for everything else. This keep MDIO access (eg from a switch + * driver) fast. + */ + if (mask & + (IXGBE_GSSR_PHY0_SM | IXGBE_GSSR_PHY1_SM | IXGBE_GSSR_SW_MNG_SM)) + usec_delay(10); + else + usec_delay(2000); } /** diff --git a/sys/dev/ixl/ixl_txrx.c b/sys/dev/ixl/ixl_txrx.c index 04b8279bdc59..bca5abd370f5 100644 --- a/sys/dev/ixl/ixl_txrx.c +++ b/sys/dev/ixl/ixl_txrx.c @@ -33,7 +33,7 @@ /* ** IXL driver TX/RX Routines: -** This was seperated to allow usage by +** This was separated to allow usage by ** both the PF and VF drivers. */ diff --git a/sys/dev/jme/if_jme.c b/sys/dev/jme/if_jme.c index d9982a2f031c..02e71d54851a 100644 --- a/sys/dev/jme/if_jme.c +++ b/sys/dev/jme/if_jme.c @@ -971,23 +971,23 @@ jme_sysctl_node(struct jme_softc *sc) child = SYSCTL_CHILDREN(device_get_sysctl_tree(sc->jme_dev)); SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_coal_to", - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, &sc->jme_tx_coal_to, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, &sc->jme_tx_coal_to, 0, sysctl_hw_jme_tx_coal_to, "I", "jme tx coalescing timeout"); SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tx_coal_pkt", - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, &sc->jme_tx_coal_pkt, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, &sc->jme_tx_coal_pkt, 0, sysctl_hw_jme_tx_coal_pkt, "I", "jme tx coalescing packet"); SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_coal_to", - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, &sc->jme_rx_coal_to, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, &sc->jme_rx_coal_to, 0, sysctl_hw_jme_rx_coal_to, "I", "jme rx coalescing timeout"); SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_coal_pkt", - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, &sc->jme_rx_coal_pkt, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, &sc->jme_rx_coal_pkt, 0, sysctl_hw_jme_rx_coal_pkt, "I", "jme rx coalescing packet"); SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "process_limit", - CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, + CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, &sc->jme_process_limit, 0, sysctl_hw_jme_proc_limit, "I", "max number of Rx events to process"); diff --git a/sys/dev/le/am7990.c b/sys/dev/le/am7990.c deleted file mode 100644 index 95184356f33b..000000000000 --- a/sys/dev/le/am7990.c +++ /dev/null @@ -1,616 +0,0 @@ -/* $NetBSD: am7990.c,v 1.68 2005/12/11 12:21:25 christos Exp $ */ - -/*- - * SPDX-License-Identifier: BSD-2-Clause AND BSD-3-Clause - * - * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace - * Simulation Facility, NASA Ames Research Center. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/bus.h> -#include <sys/endian.h> -#include <sys/lock.h> -#include <sys/mbuf.h> -#include <sys/mutex.h> -#include <sys/socket.h> - -#include <net/bpf.h> -#include <net/ethernet.h> -#include <net/if.h> -#include <net/if_arp.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_var.h> - -#include <machine/bus.h> - -#include <dev/le/lancereg.h> -#include <dev/le/lancevar.h> -#include <dev/le/am7990reg.h> -#include <dev/le/am7990var.h> - -static void am7990_meminit(struct lance_softc *); -static void am7990_rint(struct lance_softc *); -static void am7990_tint(struct lance_softc *); -static void am7990_start_locked(struct lance_softc *sc); - -#ifdef LEDEBUG -static void am7990_recv_print(struct lance_softc *, int); -static void am7990_xmit_print(struct lance_softc *, int); -#endif - -int -am7990_config(struct am7990_softc *sc, const char* name, int unit) -{ - int error, mem; - - sc->lsc.sc_meminit = am7990_meminit; - sc->lsc.sc_start_locked = am7990_start_locked; - - error = lance_config(&sc->lsc, name, unit); - if (error != 0) - return (error); - - mem = 0; - sc->lsc.sc_initaddr = mem; - mem += sizeof(struct leinit); - sc->lsc.sc_rmdaddr = mem; - mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf; - sc->lsc.sc_tmdaddr = mem; - mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf; - sc->lsc.sc_rbufaddr = mem; - mem += LEBLEN * sc->lsc.sc_nrbuf; - sc->lsc.sc_tbufaddr = mem; - mem += LEBLEN * sc->lsc.sc_ntbuf; - - if (mem > sc->lsc.sc_memsize) - panic("%s: memsize", __func__); - - lance_attach(&sc->lsc); - - return (0); -} - -void -am7990_detach(struct am7990_softc *sc) -{ - - lance_detach(&sc->lsc); -} - -/* - * Set up the initialization block and the descriptor rings. - */ -static void -am7990_meminit(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - struct leinit init; - struct lermd rmd; - struct letmd tmd; - u_long a; - int bix; - - LE_LOCK_ASSERT(sc, MA_OWNED); - - if (if_getflags(ifp) & IFF_PROMISC) - init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM; - else - init.init_mode = LE_MODE_NORMAL; - - init.init_padr[0] = (sc->sc_enaddr[1] << 8) | sc->sc_enaddr[0]; - init.init_padr[1] = (sc->sc_enaddr[3] << 8) | sc->sc_enaddr[2]; - init.init_padr[2] = (sc->sc_enaddr[5] << 8) | sc->sc_enaddr[4]; - lance_setladrf(sc, init.init_ladrf); - - sc->sc_last_rd = 0; - sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; - - a = sc->sc_addr + LE_RMDADDR(sc, 0); - init.init_rdra = a; - init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13); - - a = sc->sc_addr + LE_TMDADDR(sc, 0); - init.init_tdra = a; - init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13); - - (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); - - /* - * Set up receive ring descriptors. - */ - for (bix = 0; bix < sc->sc_nrbuf; bix++) { - a = sc->sc_addr + LE_RBUFADDR(sc, bix); - rmd.rmd0 = a; - rmd.rmd1_hadr = a >> 16; - rmd.rmd1_bits = LE_R1_OWN; - rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; - rmd.rmd3 = 0; - (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), - sizeof(rmd)); - } - - /* - * Set up transmit ring descriptors. - */ - for (bix = 0; bix < sc->sc_ntbuf; bix++) { - a = sc->sc_addr + LE_TBUFADDR(sc, bix); - tmd.tmd0 = a; - tmd.tmd1_hadr = a >> 16; - tmd.tmd1_bits = 0; - tmd.tmd2 = LE_XMD2_ONES; - tmd.tmd3 = 0; - (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), - sizeof(tmd)); - } -} - -static void -am7990_rint(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - struct mbuf *m; - struct lermd rmd; - int bix, rp; -#if defined(LANCE_REVC_BUG) - struct ether_header *eh; - /* Make sure this is short-aligned, for ether_cmp(). */ - static uint16_t bcast_enaddr[3] = { ~0, ~0, ~0 }; -#endif - - bix = sc->sc_last_rd; - - /* Process all buffers with valid data. */ - for (;;) { - rp = LE_RMDADDR(sc, bix); - (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); - - if (rmd.rmd1_bits & LE_R1_OWN) - break; - - m = NULL; - if ((rmd.rmd1_bits & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) != - (LE_R1_STP | LE_R1_ENP)) { - if (rmd.rmd1_bits & LE_R1_ERR) { -#ifdef LEDEBUG - if (rmd.rmd1_bits & LE_R1_ENP) { - if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) { - if (rmd.rmd1_bits & LE_R1_FRAM) - if_printf(ifp, - "framing error\n"); - if (rmd.rmd1_bits & LE_R1_CRC) - if_printf(ifp, - "crc mismatch\n"); - } - } else - if (rmd.rmd1_bits & LE_R1_OFLO) - if_printf(ifp, "overflow\n"); -#endif - if (rmd.rmd1_bits & LE_R1_BUFF) - if_printf(ifp, - "receive buffer error\n"); - } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) != - (LE_R1_STP | LE_R1_ENP)) - if_printf(ifp, "dropping chained buffer\n"); - } else { -#ifdef LEDEBUG - if (sc->sc_flags & LE_DEBUG) - am7990_recv_print(sc, bix); -#endif - /* Pull the packet off the interface. */ - m = lance_get(sc, LE_RBUFADDR(sc, bix), - (int)rmd.rmd3 - ETHER_CRC_LEN); - } - - rmd.rmd1_bits = LE_R1_OWN; - rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; - rmd.rmd3 = 0; - (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); - - if (++bix == sc->sc_nrbuf) - bix = 0; - - if (m != NULL) { - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); - -#ifdef LANCE_REVC_BUG - /* - * The old LANCE (Rev. C) chips have a bug which - * causes garbage to be inserted in front of the - * received packet. The workaround is to ignore - * packets with an invalid destination address - * (garbage will usually not match). - * Of course, this precludes multicast support... - */ - eh = mtod(m, struct ether_header *); - if (ether_cmp(eh->ether_dhost, sc->sc_enaddr) && - ether_cmp(eh->ether_dhost, bcast_enaddr)) { - m_freem(m); - continue; - } -#endif - - /* Pass the packet up. */ - LE_UNLOCK(sc); - if_input(ifp, m); - LE_LOCK(sc); - } else - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - } - - sc->sc_last_rd = bix; -} - -static void -am7990_tint(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - struct letmd tmd; - int bix; - - bix = sc->sc_first_td; - - for (;;) { - if (sc->sc_no_td <= 0) - break; - - (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), - sizeof(tmd)); - -#ifdef LEDEBUG - if (sc->sc_flags & LE_DEBUG) - if_printf(ifp, "trans tmd: " - "ladr %04x, hadr %02x, flags %02x, " - "bcnt %04x, mcnt %04x\n", - tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, - tmd.tmd2, tmd.tmd3); -#endif - - if (tmd.tmd1_bits & LE_T1_OWN) - break; - - if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); - - if (tmd.tmd1_bits & LE_T1_ERR) { - if (tmd.tmd3 & LE_T3_BUFF) - if_printf(ifp, "transmit buffer error\n"); - else if (tmd.tmd3 & LE_T3_UFLO) - if_printf(ifp, "underflow\n"); - if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) { - lance_init_locked(sc); - return; - } - if (tmd.tmd3 & LE_T3_LCAR) { - if (sc->sc_flags & LE_CARRIER) - if_link_state_change(ifp, - LINK_STATE_DOWN); - sc->sc_flags &= ~LE_CARRIER; - if (sc->sc_nocarrier) - (*sc->sc_nocarrier)(sc); - else - if_printf(ifp, "lost carrier\n"); - } - if (tmd.tmd3 & LE_T3_LCOL) - if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); - if (tmd.tmd3 & LE_T3_RTRY) { -#ifdef LEDEBUG - if_printf(ifp, "excessive collisions, tdr %d\n", - tmd.tmd3 & LE_T3_TDR_MASK); -#endif - if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 16); - } - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } else { - if (tmd.tmd1_bits & LE_T1_ONE) - if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); - else if (tmd.tmd1_bits & LE_T1_MORE) - /* Real number is unknown. */ - if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 2); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - } - - if (++bix == sc->sc_ntbuf) - bix = 0; - - --sc->sc_no_td; - } - - sc->sc_first_td = bix; - - sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0; -} - -/* - * Controller interrupt - */ -void -am7990_intr(void *arg) -{ - struct lance_softc *sc = arg; - if_t ifp = sc->sc_ifp; - uint16_t isr; - - LE_LOCK(sc); - - if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - lance_init_locked(sc); - LE_UNLOCK(sc); - return; - } - - isr = (*sc->sc_rdcsr)(sc, LE_CSR0); -#if defined(LEDEBUG) && LEDEBUG > 1 - if (sc->sc_flags & LE_DEBUG) - if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr); -#endif - if ((isr & LE_C0_INTR) == 0) { - LE_UNLOCK(sc); - return; - } - - /* - * Clear interrupt source flags and turn off interrupts. If we - * don't clear these flags before processing their sources we - * could completely miss some interrupt events as the NIC can - * change these flags while we're in this handler. We toggle - * the interrupt enable bit in order to keep receiving them - * (some chips work without this, some don't). - */ - (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD | - LE_C0_STOP | LE_C0_STRT | LE_C0_INIT)); - - if (isr & LE_C0_ERR) { - if (isr & LE_C0_BABL) { -#ifdef LEDEBUG - if_printf(ifp, "babble\n"); -#endif - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } -#if 0 - if (isr & LE_C0_CERR) { - if_printf(ifp, "collision error\n"); - if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); - } -#endif - if (isr & LE_C0_MISS) { -#ifdef LEDEBUG - if_printf(ifp, "missed packet\n"); -#endif - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - } - if (isr & LE_C0_MERR) { - if_printf(ifp, "memory error\n"); - lance_init_locked(sc); - LE_UNLOCK(sc); - return; - } - } - - if ((isr & LE_C0_RXON) == 0) { - if_printf(ifp, "receiver disabled\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - lance_init_locked(sc); - LE_UNLOCK(sc); - return; - } - if ((isr & LE_C0_TXON) == 0) { - if_printf(ifp, "transmitter disabled\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - lance_init_locked(sc); - LE_UNLOCK(sc); - return; - } - - /* - * Pretend we have carrier; if we don't this will be cleared shortly. - */ - if (!(sc->sc_flags & LE_CARRIER)) - if_link_state_change(ifp, LINK_STATE_UP); - sc->sc_flags |= LE_CARRIER; - - if (isr & LE_C0_RINT) - am7990_rint(sc); - if (isr & LE_C0_TINT) - am7990_tint(sc); - - /* Enable interrupts again. */ - (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); - - if (!if_sendq_empty(ifp)) - am7990_start_locked(sc); - - LE_UNLOCK(sc); -} - -/* - * Set up output on interface. - * Get another datagram to send off of the interface queue, and map it to the - * interface before starting the output. - */ -static void -am7990_start_locked(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - struct letmd tmd; - struct mbuf *m; - int bix, enq, len, rp; - - LE_LOCK_ASSERT(sc, MA_OWNED); - - if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != - IFF_DRV_RUNNING) - return; - - bix = sc->sc_last_td; - enq = 0; - - for (; sc->sc_no_td < sc->sc_ntbuf && - !if_sendq_empty(ifp);) { - rp = LE_TMDADDR(sc, bix); - (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); - - if (tmd.tmd1_bits & LE_T1_OWN) { - if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); - if_printf(ifp, - "missing buffer, no_td = %d, last_td = %d\n", - sc->sc_no_td, sc->sc_last_td); - } - - m = if_dequeue(ifp); - if (m == NULL) - break; - - /* - * If BPF is listening on this interface, let it see the packet - * before we commit it to the wire. - */ - BPF_MTAP(ifp, m); - - /* - * Copy the mbuf chain into the transmit buffer. - */ - len = lance_put(sc, LE_TBUFADDR(sc, bix), m); - -#ifdef LEDEBUG - if (len > ETHERMTU + ETHER_HDR_LEN) - if_printf(ifp, "packet length %d\n", len); -#endif - - /* - * Init transmit registers, and set transmit start flag. - */ - tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP; - tmd.tmd2 = -len | LE_XMD2_ONES; - tmd.tmd3 = 0; - - (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); - -#ifdef LEDEBUG - if (sc->sc_flags & LE_DEBUG) - am7990_xmit_print(sc, bix); -#endif - - (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); - enq++; - - if (++bix == sc->sc_ntbuf) - bix = 0; - - if (++sc->sc_no_td == sc->sc_ntbuf) { - if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); - break; - } - } - - sc->sc_last_td = bix; - - if (enq > 0) - sc->sc_wdog_timer = 5; -} - -#ifdef LEDEBUG -static void -am7990_recv_print(struct lance_softc *sc, int no) -{ - if_t ifp = sc->sc_ifp; - struct ether_header eh; - struct lermd rmd; - uint16_t len; - - (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); - len = rmd.rmd3; - if_printf(ifp, "receive buffer %d, len = %d\n", no, len); - if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); - if_printf(ifp, - "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", - rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3); - if (len - ETHER_CRC_LEN >= sizeof(eh)) { - (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); - if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); - printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), - ntohs(eh.ether_type)); - } -} - -static void -am7990_xmit_print(struct lance_softc *sc, int no) -{ - if_t ifp = sc->sc_ifp; - struct ether_header eh; - struct letmd tmd; - uint16_t len; - - (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); - len = -tmd.tmd2; - if_printf(ifp, "transmit buffer %d, len = %d\n", no, len); - if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); - if_printf(ifp, - "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", - tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3); - if (len >= sizeof(eh)) { - (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); - if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); - printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), - ntohs(eh.ether_type)); - } -} -#endif /* LEDEBUG */ diff --git a/sys/dev/le/am79900.c b/sys/dev/le/am79900.c deleted file mode 100644 index c680fd5e2dc2..000000000000 --- a/sys/dev/le/am79900.c +++ /dev/null @@ -1,651 +0,0 @@ -/* $NetBSD: am79900.c,v 1.17 2005/12/24 20:27:29 perry Exp $ */ - -/*- - * SPDX-License-Identifier: BSD-2-Clause AND BSD-3-Clause - * - * Copyright (c) 1997 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Jason R. Thorpe. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1998 - * Matthias Drochner. All rights reserved. - * Copyright (c) 1995 Charles M. Hannum. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/bus.h> -#include <sys/endian.h> -#include <sys/lock.h> -#include <sys/mbuf.h> -#include <sys/mutex.h> -#include <sys/socket.h> - -#include <net/bpf.h> -#include <net/ethernet.h> -#include <net/if.h> -#include <net/if_arp.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_var.h> - -#include <machine/bus.h> - -#include <dev/le/lancereg.h> -#include <dev/le/lancevar.h> -#include <dev/le/am79900reg.h> -#include <dev/le/am79900var.h> - -static void am79900_meminit(struct lance_softc *); -static void am79900_rint(struct lance_softc *); -static void am79900_tint(struct lance_softc *); -static void am79900_start_locked(struct lance_softc *sc); - -#ifdef LEDEBUG -static void am79900_recv_print(struct lance_softc *, int); -static void am79900_xmit_print(struct lance_softc *, int); -#endif - -int -am79900_config(struct am79900_softc *sc, const char* name, int unit) -{ - int error, mem; - - sc->lsc.sc_meminit = am79900_meminit; - sc->lsc.sc_start_locked = am79900_start_locked; - - error = lance_config(&sc->lsc, name, unit); - if (error != 0) - return (error); - - mem = 0; - sc->lsc.sc_initaddr = mem; - mem += sizeof(struct leinit); - sc->lsc.sc_rmdaddr = mem; - mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf; - sc->lsc.sc_tmdaddr = mem; - mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf; - sc->lsc.sc_rbufaddr = mem; - mem += LEBLEN * sc->lsc.sc_nrbuf; - sc->lsc.sc_tbufaddr = mem; - mem += LEBLEN * sc->lsc.sc_ntbuf; - - if (mem > sc->lsc.sc_memsize) - panic("%s: memsize", __func__); - - lance_attach(&sc->lsc); - - return (0); -} - -void -am79900_detach(struct am79900_softc *sc) -{ - - lance_detach(&sc->lsc); -} - -/* - * Set up the initialization block and the descriptor rings. - */ -static void -am79900_meminit(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - struct leinit init; - struct lermd rmd; - struct letmd tmd; - u_long a; - int bix; - - LE_LOCK_ASSERT(sc, MA_OWNED); - - if (if_getflags(ifp) & IFF_PROMISC) - init.init_mode = LE_HTOLE32(LE_MODE_NORMAL | LE_MODE_PROM); - else - init.init_mode = LE_HTOLE32(LE_MODE_NORMAL); - - init.init_mode |= LE_HTOLE32(((ffs(sc->sc_ntbuf) - 1) << 28) | - ((ffs(sc->sc_nrbuf) - 1) << 20)); - - init.init_padr[0] = LE_HTOLE32(sc->sc_enaddr[0] | - (sc->sc_enaddr[1] << 8) | (sc->sc_enaddr[2] << 16) | - (sc->sc_enaddr[3] << 24)); - init.init_padr[1] = LE_HTOLE32(sc->sc_enaddr[4] | - (sc->sc_enaddr[5] << 8)); - lance_setladrf(sc, init.init_ladrf); - - sc->sc_last_rd = 0; - sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; - - a = sc->sc_addr + LE_RMDADDR(sc, 0); - init.init_rdra = LE_HTOLE32(a); - - a = sc->sc_addr + LE_TMDADDR(sc, 0); - init.init_tdra = LE_HTOLE32(a); - - (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); - - /* - * Set up receive ring descriptors. - */ - for (bix = 0; bix < sc->sc_nrbuf; bix++) { - a = sc->sc_addr + LE_RBUFADDR(sc, bix); - rmd.rmd0 = LE_HTOLE32(a); - rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES | - (-LEBLEN & 0xfff)); - rmd.rmd2 = 0; - rmd.rmd3 = 0; - (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), - sizeof(rmd)); - } - - /* - * Set up transmit ring descriptors. - */ - for (bix = 0; bix < sc->sc_ntbuf; bix++) { - a = sc->sc_addr + LE_TBUFADDR(sc, bix); - tmd.tmd0 = LE_HTOLE32(a); - tmd.tmd1 = LE_HTOLE32(LE_T1_ONES); - tmd.tmd2 = 0; - tmd.tmd3 = 0; - (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), - sizeof(tmd)); - } -} - -static inline void -am79900_rint(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - struct mbuf *m; - struct lermd rmd; - uint32_t rmd1; - int bix, rp; -#if defined(__i386__) - struct ether_header *eh; -#endif - - bix = sc->sc_last_rd; - - /* Process all buffers with valid data. */ - for (;;) { - rp = LE_RMDADDR(sc, bix); - (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); - - rmd1 = LE_LE32TOH(rmd.rmd1); - if (rmd1 & LE_R1_OWN) - break; - - m = NULL; - if ((rmd1 & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) != - (LE_R1_STP | LE_R1_ENP)){ - if (rmd1 & LE_R1_ERR) { -#ifdef LEDEBUG - if (rmd1 & LE_R1_ENP) { - if ((rmd1 & LE_R1_OFLO) == 0) { - if (rmd1 & LE_R1_FRAM) - if_printf(ifp, - "framing error\n"); - if (rmd1 & LE_R1_CRC) - if_printf(ifp, - "crc mismatch\n"); - } - } else - if (rmd1 & LE_R1_OFLO) - if_printf(ifp, "overflow\n"); -#endif - if (rmd1 & LE_R1_BUFF) - if_printf(ifp, - "receive buffer error\n"); - } else if ((rmd1 & (LE_R1_STP | LE_R1_ENP)) != - (LE_R1_STP | LE_R1_ENP)) - if_printf(ifp, "dropping chained buffer\n"); - } else { -#ifdef LEDEBUG - if (sc->sc_flags & LE_DEBUG) - am79900_recv_print(sc, bix); -#endif - /* Pull the packet off the interface. */ - m = lance_get(sc, LE_RBUFADDR(sc, bix), - (LE_LE32TOH(rmd.rmd2) & 0xfff) - ETHER_CRC_LEN); - } - - rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES | - (-LEBLEN & 0xfff)); - rmd.rmd2 = 0; - rmd.rmd3 = 0; - (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); - - if (++bix == sc->sc_nrbuf) - bix = 0; - - if (m != NULL) { - if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); - -#if defined(__i386__) - /* - * The VMware LANCE does not present IFF_SIMPLEX - * behavior on multicast packets. Thus drop the - * packet if it is from ourselves. - */ - eh = mtod(m, struct ether_header *); - if (!ether_cmp(eh->ether_shost, sc->sc_enaddr)) { - m_freem(m); - continue; - } -#endif - - /* Pass the packet up. */ - LE_UNLOCK(sc); - if_input(ifp, m); - LE_LOCK(sc); - } else - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - } - - sc->sc_last_rd = bix; -} - -static inline void -am79900_tint(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - struct letmd tmd; - uint32_t tmd1, tmd2; - int bix; - - bix = sc->sc_first_td; - - for (;;) { - if (sc->sc_no_td <= 0) - break; - - (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), - sizeof(tmd)); - - tmd1 = LE_LE32TOH(tmd.tmd1); - -#ifdef LEDEBUG - if (sc->sc_flags & LE_DEBUG) - if_printf(ifp, "trans tmd: " - "adr %08x, flags/blen %08x\n", - LE_LE32TOH(tmd.tmd0), tmd1); -#endif - - if (tmd1 & LE_T1_OWN) - break; - - if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); - - if (tmd1 & LE_T1_ERR) { - tmd2 = LE_LE32TOH(tmd.tmd2); - if (tmd2 & LE_T2_BUFF) - if_printf(ifp, "transmit buffer error\n"); - else if (tmd2 & LE_T2_UFLO) - if_printf(ifp, "underflow\n"); - if (tmd2 & (LE_T2_BUFF | LE_T2_UFLO)) { - lance_init_locked(sc); - return; - } - if (tmd2 & LE_T2_LCAR) { - if (sc->sc_flags & LE_CARRIER) - if_link_state_change(ifp, - LINK_STATE_DOWN); - sc->sc_flags &= ~LE_CARRIER; - if (sc->sc_nocarrier) - (*sc->sc_nocarrier)(sc); - else - if_printf(ifp, "lost carrier\n"); - } - if (tmd2 & LE_T2_LCOL) - if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); - if (tmd2 & LE_T2_RTRY) { -#ifdef LEDEBUG - if_printf(ifp, "excessive collisions\n"); -#endif - if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 16); - } - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } else { - if (tmd1 & LE_T1_ONE) - if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); - else if (tmd1 & LE_T1_MORE) - /* Real number is unknown. */ - if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 2); - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); - } - - if (++bix == sc->sc_ntbuf) - bix = 0; - - --sc->sc_no_td; - } - - sc->sc_first_td = bix; - - sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0; -} - -/* - * Controller interrupt - */ -void -am79900_intr(void *arg) -{ - struct lance_softc *sc = arg; - if_t ifp = sc->sc_ifp; - uint16_t isr; - - LE_LOCK(sc); - - if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) { - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - lance_init_locked(sc); - LE_UNLOCK(sc); - return; - } - - isr = (*sc->sc_rdcsr)(sc, LE_CSR0); -#if defined(LEDEBUG) && LEDEBUG > 1 - if (sc->sc_flags & LE_DEBUG) - if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr); -#endif - if ((isr & LE_C0_INTR) == 0) { - LE_UNLOCK(sc); - return; - } - - /* - * Clear interrupt source flags and turn off interrupts. If we - * don't clear these flags before processing their sources we - * could completely miss some interrupt events as the NIC can - * change these flags while we're in this handler. We toggle - * the interrupt enable bit in order to keep receiving them - * (some chips work without this, some don't). - */ - (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD | - LE_C0_STOP | LE_C0_STRT | LE_C0_INIT)); - - if (isr & LE_C0_ERR) { - if (isr & LE_C0_BABL) { -#ifdef LEDEBUG - if_printf(ifp, "babble\n"); -#endif - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - } -#if 0 - if (isr & LE_C0_CERR) { - if_printf(ifp, "collision error\n"); - if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); - } -#endif - if (isr & LE_C0_MISS) { -#ifdef LEDEBUG - if_printf(ifp, "missed packet\n"); -#endif - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - } - if (isr & LE_C0_MERR) { - if_printf(ifp, "memory error\n"); - lance_init_locked(sc); - LE_UNLOCK(sc); - return; - } - } - - if ((isr & LE_C0_RXON) == 0) { - if_printf(ifp, "receiver disabled\n"); - if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); - lance_init_locked(sc); - LE_UNLOCK(sc); - return; - } - if ((isr & LE_C0_TXON) == 0) { - if_printf(ifp, "transmitter disabled\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - lance_init_locked(sc); - LE_UNLOCK(sc); - return; - } - - /* - * Pretend we have carrier; if we don't this will be cleared shortly. - */ - if (!(sc->sc_flags & LE_CARRIER)) - if_link_state_change(ifp, LINK_STATE_UP); - sc->sc_flags |= LE_CARRIER; - - if (isr & LE_C0_RINT) - am79900_rint(sc); - if (isr & LE_C0_TINT) - am79900_tint(sc); - - /* Enable interrupts again. */ - (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); - - if (!if_sendq_empty(ifp)) - am79900_start_locked(sc); - - LE_UNLOCK(sc); -} - -/* - * Set up output on interface. - * Get another datagram to send off of the interface queue, and map it to the - * interface before starting the output. - */ -static void -am79900_start_locked(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - struct letmd tmd; - struct mbuf *m; - int bix, enq, len, rp; - - LE_LOCK_ASSERT(sc, MA_OWNED); - - if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != - IFF_DRV_RUNNING) - return; - - bix = sc->sc_last_td; - enq = 0; - - for (; sc->sc_no_td < sc->sc_ntbuf && - !if_sendq_empty(ifp);) { - rp = LE_TMDADDR(sc, bix); - (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); - - if (LE_LE32TOH(tmd.tmd1) & LE_T1_OWN) { - if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); - if_printf(ifp, - "missing buffer, no_td = %d, last_td = %d\n", - sc->sc_no_td, sc->sc_last_td); - } - - m = if_dequeue(ifp); - if (m == NULL) - break; - - /* - * If BPF is listening on this interface, let it see the packet - * before we commit it to the wire. - */ - BPF_MTAP(ifp, m); - - /* - * Copy the mbuf chain into the transmit buffer. - */ - len = lance_put(sc, LE_TBUFADDR(sc, bix), m); - -#ifdef LEDEBUG - if (len > ETHERMTU + ETHER_HDR_LEN) - if_printf(ifp, "packet length %d\n", len); -#endif - - /* - * Init transmit registers, and set transmit start flag. - */ - tmd.tmd1 = LE_HTOLE32(LE_T1_OWN | LE_T1_STP | LE_T1_ENP | - LE_T1_ONES | (-len & 0xfff)); - tmd.tmd2 = 0; - tmd.tmd3 = 0; - - (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); - -#ifdef LEDEBUG - if (sc->sc_flags & LE_DEBUG) - am79900_xmit_print(sc, bix); -#endif - - (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); - enq++; - - if (++bix == sc->sc_ntbuf) - bix = 0; - - if (++sc->sc_no_td == sc->sc_ntbuf) { - if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); - break; - } - } - - sc->sc_last_td = bix; - - if (enq > 0) - sc->sc_wdog_timer = 5; -} - -#ifdef LEDEBUG -static void -am79900_recv_print(struct lance_softc *sc, int no) -{ - if_t ifp = sc->sc_ifp; - struct ether_header eh; - struct lermd rmd; - uint16_t len; - - (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); - len = LE_LE32TOH(rmd.rmd2) & 0xfff; - if_printf(ifp, "receive buffer %d, len = %d\n", no, len); - if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); - if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(rmd.rmd0), - LE_LE32TOH(rmd.rmd1)); - if (len - ETHER_CRC_LEN >= sizeof(eh)) { - (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); - if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); - printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), - ntohs(eh.ether_type)); - } -} - -static void -am79900_xmit_print(struct lance_softc *sc, int no) -{ - if_t ifp = sc->sc_ifp; - struct ether_header eh; - struct letmd tmd; - uint16_t len; - - (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); - len = -(LE_LE32TOH(tmd.tmd1) & 0xfff); - if_printf(ifp, "transmit buffer %d, len = %d\n", no, len); - if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); - if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(tmd.tmd0), - LE_LE32TOH(tmd.tmd1)); - if (len >= sizeof(eh)) { - (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); - if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); - printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), - ntohs(eh.ether_type)); - } -} -#endif /* LEDEBUG */ diff --git a/sys/dev/le/am79900reg.h b/sys/dev/le/am79900reg.h deleted file mode 100644 index bd9b8b49cfdb..000000000000 --- a/sys/dev/le/am79900reg.h +++ /dev/null @@ -1,148 +0,0 @@ -/* $NetBSD: am79900reg.h,v 1.8 2005/12/11 12:21:25 christos Exp $ */ - -/*- - * SPDX-License-Identifier: BSD-2-Clause AND BSD-3-Clause - * - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - -#ifndef _DEV_LE_AM79900REG_H_ -#define _DEV_LE_AM79900REG_H_ - -/* - * Receive message descriptor - */ -struct lermd { - uint32_t rmd0; - uint32_t rmd1; - uint32_t rmd2; - int32_t rmd3; -}; - -/* - * Transmit message descriptor - */ -struct letmd { - uint32_t tmd0; - uint32_t tmd1; - uint32_t tmd2; - int32_t tmd3; -}; - -/* - * Initialization block - */ -struct leinit { - uint32_t init_mode; /* +0x0000 */ - uint32_t init_padr[2]; /* +0x0002 */ - uint16_t init_ladrf[4]; /* +0x0008 */ - uint32_t init_rdra; /* +0x0010 */ - uint32_t init_tdra; /* +0x0014 */ - int32_t pad; /* Pad to 8 ints. */ -}; - -/* Receive message descriptor 1 (rmd1_bits) */ -#define LE_R1_OWN (1U << 31) /* LANCE owns the packet */ -#define LE_R1_ERR (1U << 30) /* error summary */ -#define LE_R1_FRAM (1U << 29) /* framing error */ -#define LE_R1_OFLO (1U << 28) /* overflow error */ -#define LE_R1_CRC (1U << 27) /* CRC error */ -#define LE_R1_BUFF (1U << 26) /* buffer error */ -#define LE_R1_STP (1U << 25) /* start of packet */ -#define LE_R1_ENP (1U << 24) /* end of packet */ -#define LE_R1_ONES (0xfU << 12) /* must be ones */ -#define LE_R1_BCNT_MASK (0xfff) /* byte count mask */ - -#define LE_R1_BITS \ - "\20\40OWN\37ERR\36FRAM\35OFLO\34CRC\33BUFF\32STP\31ENP" - -/* Transmit message descriptor 1 (tmd1_bits) */ -#define LE_T1_OWN (1U << 31) /* LANCE owns the packet */ -#define LE_T1_ERR (1U << 30) /* error summary */ -#define LE_T1_ADD_FCS (1U << 29) /* add FCS (PCnet-PCI) */ -#define LE_T1_NO_FCS (1U << 29) /* no FCS (ILACC) */ -#define LE_T1_MORE (1U << 28) /* multiple collisions */ -#define LE_T1_LTINT (1U << 28) /* transmit interrupt (if LTINTEN) */ -#define LE_T1_ONE (1U << 27) /* single collision */ -#define LE_T1_DEF (1U << 26) /* deferred transmit */ -#define LE_T1_STP (1U << 25) /* start of packet */ -#define LE_T1_ENP (1U << 24) /* end of packet */ -#define LE_T1_ONES (0xfU << 12) /* must be ones */ -#define LE_T1_BCNT_MASK (0xfff) /* byte count mask */ - -#define LE_T1_BITS \ - "\20\40OWN\37ERR\36RES\35MORE\34ONE\33DEF\32STP\31ENP" - -/* Transmit message descriptor 3 (tmd3) */ -#define LE_T2_BUFF (1U << 31) /* buffer error */ -#define LE_T2_UFLO (1U << 30) /* underflow error */ -#define LE_T2_EXDEF (1U << 29) /* excessive defferral */ -#define LE_T2_LCOL (1U << 28) /* late collision */ -#define LE_T2_LCAR (1U << 27) /* loss of carrier */ -#define LE_T2_RTRY (1U << 26) /* retry error */ -#if 0 -#define LE_T3_TDR_MASK 0x03ff /* time domain reflectometry counter */ -#endif - -#define LE_T3_BITS \ - "\12\40BUFF\37UFLO\35LCOL\34LCAR\33RTRY" - -#endif /* !_DEV_LE_AM7990REG_H_ */ diff --git a/sys/dev/le/am79900var.h b/sys/dev/le/am79900var.h deleted file mode 100644 index 5090237155c5..000000000000 --- a/sys/dev/le/am79900var.h +++ /dev/null @@ -1,56 +0,0 @@ -/* $NetBSD: am79900var.h,v 1.4 2005/12/11 12:21:25 christos Exp $ */ - -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace - * Simulation Facility, NASA Ames Research Center. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef _DEV_LE_AM79900VAR_H_ -#define _DEV_LE_AM79900VAR_H_ - -/* - * Ethernet software status per device. - * - * NOTE: this structure MUST be the first element in machine-dependent - * le_softc structures! This is designed SPECIFICALLY to make it possible - * to simply cast a "void *" to "struct le_softc *" or to - * "struct am79900_softc *". Among other things, this saves a lot of hair - * in the interrupt handlers. - */ -struct am79900_softc { - struct lance_softc lsc; -}; - -int am79900_config(struct am79900_softc *, const char*, int); -void am79900_detach(struct am79900_softc *); -void am79900_intr(void *); - -#endif /* _DEV_LE_AM79900VAR_H_ */ diff --git a/sys/dev/le/am7990reg.h b/sys/dev/le/am7990reg.h deleted file mode 100644 index 6314c1a1e9cf..000000000000 --- a/sys/dev/le/am7990reg.h +++ /dev/null @@ -1,181 +0,0 @@ -/* $NetBSD: am7990reg.h,v 1.11 2005/12/11 12:21:25 christos Exp $ */ - -/*- - * Copyright (c) 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - -#ifndef _DEV_LE_AM7990REG_H_ -#define _DEV_LE_AM7990REG_H_ - -/* - * Receive message descriptor - */ -struct lermd { - uint16_t rmd0; -#if BYTE_ORDER == BIG_ENDIAN - uint8_t rmd1_bits; - uint8_t rmd1_hadr; -#else - uint8_t rmd1_hadr; - uint8_t rmd1_bits; -#endif - int16_t rmd2; - uint16_t rmd3; -} __packed; - -/* - * Transmit message descriptor - */ -struct letmd { - uint16_t tmd0; -#if BYTE_ORDER == BIG_ENDIAN - uint8_t tmd1_bits; - uint8_t tmd1_hadr; -#else - uint8_t tmd1_hadr; - uint8_t tmd1_bits; -#endif - int16_t tmd2; - uint16_t tmd3; -} __packed; - -/* - * Initialization block - */ -struct leinit { - uint16_t init_mode; /* +0x0000 */ - uint16_t init_padr[3]; /* +0x0002 */ - uint16_t init_ladrf[4]; /* +0x0008 */ - uint16_t init_rdra; /* +0x0010 */ - uint16_t init_rlen; /* +0x0012 */ - uint16_t init_tdra; /* +0x0014 */ - uint16_t init_tlen; /* +0x0016 */ - int16_t pad0[4]; /* Pad to 16 shorts. */ -} __packed; - -/* Receive message descriptor 1 (rmd1_bits) */ -#define LE_R1_OWN 0x80 /* LANCE owns the packet */ -#define LE_R1_ERR 0x40 /* error summary */ -#define LE_R1_FRAM 0x20 /* framing error */ -#define LE_R1_OFLO 0x10 /* overflow error */ -#define LE_R1_CRC 0x08 /* CRC error */ -#define LE_R1_BUFF 0x04 /* buffer error */ -#define LE_R1_STP 0x02 /* start of packet */ -#define LE_R1_ENP 0x01 /* end of packet */ - -#define LE_R1_BITS \ - "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3BUFF\2STP\1ENP" - -/* Transmit message descriptor 1 (tmd1_bits) */ -#define LE_T1_OWN 0x80 /* LANCE owns the packet */ -#define LE_T1_ERR 0x40 /* error summary */ -#define LE_T1_MORE 0x10 /* multiple collisions */ -#define LE_T1_ONE 0x08 /* single collision */ -#define LE_T1_DEF 0x04 /* deferred transmit */ -#define LE_T1_STP 0x02 /* start of packet */ -#define LE_T1_ENP 0x01 /* end of packet */ - -#define LE_T1_BITS \ - "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP" - -/* Transmit message descriptor 3 (tmd3) */ -#define LE_T3_BUFF 0x8000 /* buffer error */ -#define LE_T3_UFLO 0x4000 /* underflow error */ -#define LE_T3_LCOL 0x1000 /* late collision */ -#define LE_T3_LCAR 0x0800 /* loss of carrier */ -#define LE_T3_RTRY 0x0400 /* retry error */ -#define LE_T3_TDR_MASK 0x03ff /* time domain reflectometry counter */ - -#define LE_XMD2_ONES 0xf000 - -#define LE_T3_BITS \ - "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY" - -/* - * PCnet-ISA defines which are not available on LANCE 7990. - */ - -/* (ISA) Bus Configuration Registers */ -#define LE_BCR_MSRDA 0x0000 -#define LE_BCR_MSWRA 0x0001 -#define LE_BCR_MC 0x0002 -#define LE_BCR_LED1 0x0005 -#define LE_BCR_LED2 0x0006 -#define LE_BCR_LED3 0x0007 - -/* Bus configurations bits (MC) */ -#define LE_MC_EADISEL 0x0008 /* EADI selection */ -#define LE_MC_AWAKE 0x0004 /* auto-wake */ -#define LE_MC_ASEL 0x0002 /* auto selection */ -#define LE_MC_XMAUSEL 0x0001 /* external MAU selection */ - -/* LED bis (LED[123]) */ -#define LE_LED_LEDOUT 0x8000 -#define LE_LED_PSE 0x0080 -#define LE_LED_XMTE 0x0010 -#define LE_LED_PVPE 0x0008 -#define LE_LED_PCVE 0x0004 -#define LE_LED_JABE 0x0002 -#define LE_LED_COLE 0x0001 - -#endif /* !_DEV_LE_AM7990REG_H_ */ diff --git a/sys/dev/le/am7990var.h b/sys/dev/le/am7990var.h deleted file mode 100644 index 274a69c6616d..000000000000 --- a/sys/dev/le/am7990var.h +++ /dev/null @@ -1,56 +0,0 @@ -/* $NetBSD: am7990var.h,v 1.23 2005/12/11 12:21:25 christos Exp $ */ - -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace - * Simulation Facility, NASA Ames Research Center. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef _DEV_LE_AM7990VAR_H_ -#define _DEV_LE_AM7990VAR_H_ - -/* - * Ethernet software status per device. - * - * NOTE: this structure MUST be the first element in machine-dependent - * le_softc structures! This is designed SPECIFICALLY to make it possible - * to simply cast a "void *" to "struct le_softc *" or to - * "struct am7990_softc *". Among other things, this saves a lot of hair - * in the interrupt handlers. - */ -struct am7990_softc { - struct lance_softc lsc; -}; - -int am7990_config(struct am7990_softc *, const char*, int); -void am7990_detach(struct am7990_softc *); -void am7990_intr(void *); - -#endif /* !_DEV_LE_AM7990VAR_H_ */ diff --git a/sys/dev/le/if_le_isa.c b/sys/dev/le/if_le_isa.c deleted file mode 100644 index e3c9c21df42e..000000000000 --- a/sys/dev/le/if_le_isa.c +++ /dev/null @@ -1,494 +0,0 @@ -/* $NetBSD: if_le_isa.c,v 1.41 2005/12/24 20:27:41 perry Exp $ */ - -/*- - * SPDX-License-Identifier: BSD-2-Clause AND BSD-3-Clause - * - * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace - * Simulation Facility, NASA Ames Research Center. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/endian.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/module.h> -#include <sys/mutex.h> -#include <sys/resource.h> -#include <sys/rman.h> -#include <sys/socket.h> - -#include <net/ethernet.h> -#include <net/if.h> -#include <net/if_media.h> - -#include <machine/bus.h> -#include <machine/resource.h> - -#include <isa/isavar.h> - -#include <dev/le/lancereg.h> -#include <dev/le/lancevar.h> -#include <dev/le/am7990var.h> - -#define LE_ISA_MEMSIZE (16*1024) -#define PCNET_RDP 0x10 -#define PCNET_RAP 0x12 - -struct le_isa_softc { - struct am7990_softc sc_am7990; /* glue to MI code */ - - bus_size_t sc_rap; /* offsets to LANCE... */ - bus_size_t sc_rdp; /* ...registers */ - - struct resource *sc_rres; - - struct resource *sc_dres; - - struct resource *sc_ires; - void *sc_ih; - - bus_dma_tag_t sc_pdmat; - bus_dma_tag_t sc_dmat; - bus_dmamap_t sc_dmam; -}; - -static device_probe_t le_isa_probe; -static device_attach_t le_isa_attach; -static device_detach_t le_isa_detach; -static device_resume_t le_isa_resume; -static device_suspend_t le_isa_suspend; - -static device_method_t le_isa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, le_isa_probe), - DEVMETHOD(device_attach, le_isa_attach), - DEVMETHOD(device_detach, le_isa_detach), - /* We can just use the suspend method here. */ - DEVMETHOD(device_shutdown, le_isa_suspend), - DEVMETHOD(device_suspend, le_isa_suspend), - DEVMETHOD(device_resume, le_isa_resume), - - { 0, 0 } -}; - -struct le_isa_param { - const char *name; - u_long iosize; - bus_size_t rap; - bus_size_t rdp; - bus_size_t macstart; - int macstride; -} static const le_isa_params[] = { - { "BICC Isolan", 24, 0xe, 0xc, 0, 2 }, - { "Novell NE2100", 16, 0x12, 0x10, 0, 1 } -}; - -static struct isa_pnp_id le_isa_ids[] = { - { 0x0322690e, "Cabletron E2200 Single Chip" }, /* CSI2203 */ - { 0x0110490a, "Boca LANCard Combo" }, /* BRI1001 */ - { 0x0100a60a, "Melco Inc. LGY-IV" }, /* BUF0001 */ - { 0xd880d041, "Novell NE2100" }, /* PNP80D8 */ - { 0x0082d041, "Cabletron E2100 Series DNI" }, /* PNP8200 */ - { 0x3182d041, "AMD AM1500T/AM2100" }, /* PNP8231 */ - { 0x8c82d041, "AMD PCnet-ISA" }, /* PNP828C */ - { 0x8d82d041, "AMD PCnet-32" }, /* PNP828D */ - { 0xcefaedfe, "Racal InterLan EtherBlaster" }, /* _WMFACE */ - { 0, NULL } -}; - -static void le_isa_wrcsr(struct lance_softc *, uint16_t, uint16_t); -static uint16_t le_isa_rdcsr(struct lance_softc *, uint16_t); -static bus_dmamap_callback_t le_isa_dma_callback; -static int le_isa_probe_legacy(device_t, const struct le_isa_param *); - -static void -le_isa_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) -{ - struct le_isa_softc *lesc = (struct le_isa_softc *)sc; - - bus_write_2(lesc->sc_rres, lesc->sc_rap, port); - bus_barrier(lesc->sc_rres, lesc->sc_rap, 2, BUS_SPACE_BARRIER_WRITE); - bus_write_2(lesc->sc_rres, lesc->sc_rdp, val); -} - -static uint16_t -le_isa_rdcsr(struct lance_softc *sc, uint16_t port) -{ - struct le_isa_softc *lesc = (struct le_isa_softc *)sc; - - bus_write_2(lesc->sc_rres, lesc->sc_rap, port); - bus_barrier(lesc->sc_rres, lesc->sc_rap, 2, BUS_SPACE_BARRIER_WRITE); - return (bus_read_2(lesc->sc_rres, lesc->sc_rdp)); -} - -static void -le_isa_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) -{ - struct lance_softc *sc = (struct lance_softc *)xsc; - - if (error != 0) - return; - KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__)); - sc->sc_addr = segs[0].ds_addr; -} - -static int -le_isa_probe_legacy(device_t dev, const struct le_isa_param *leip) -{ - struct le_isa_softc *lesc; - struct lance_softc *sc; - int error, i; - - lesc = device_get_softc(dev); - sc = &lesc->sc_am7990.lsc; - - i = 0; - lesc->sc_rres = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &i, - leip->iosize, RF_ACTIVE); - if (lesc->sc_rres == NULL) - return (ENXIO); - lesc->sc_rap = leip->rap; - lesc->sc_rdp = leip->rdp; - - /* Stop the chip and put it in a known state. */ - le_isa_wrcsr(sc, LE_CSR0, LE_C0_STOP); - DELAY(100); - if (le_isa_rdcsr(sc, LE_CSR0) != LE_C0_STOP) { - error = ENXIO; - goto fail; - } - le_isa_wrcsr(sc, LE_CSR3, 0); - error = 0; - - fail: - bus_release_resource(dev, SYS_RES_IOPORT, - rman_get_rid(lesc->sc_rres), lesc->sc_rres); - return (error); -} - -static int -le_isa_probe(device_t dev) -{ - int i; - - switch (ISA_PNP_PROBE(device_get_parent(dev), dev, le_isa_ids)) { - case 0: - return (BUS_PROBE_DEFAULT); - case ENOENT: - for (i = 0; i < nitems(le_isa_params); i++) { - if (le_isa_probe_legacy(dev, &le_isa_params[i]) == 0) { - device_set_desc(dev, le_isa_params[i].name); - return (BUS_PROBE_DEFAULT); - } - } - /* FALLTHROUGH */ - case ENXIO: - default: - return (ENXIO); - } -} - -static int -le_isa_attach(device_t dev) -{ - struct le_isa_softc *lesc; - struct lance_softc *sc; - bus_size_t macstart, rap, rdp; - int error, i, j, macstride; - - lesc = device_get_softc(dev); - sc = &lesc->sc_am7990.lsc; - - LE_LOCK_INIT(sc, device_get_nameunit(dev)); - - j = 0; - switch (ISA_PNP_PROBE(device_get_parent(dev), dev, le_isa_ids)) { - case 0: - lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT, - &j, RF_ACTIVE); - rap = PCNET_RAP; - rdp = PCNET_RDP; - macstart = 0; - macstride = 1; - break; - case ENOENT: - for (i = 0; i < nitems(le_isa_params); i++) { - if (le_isa_probe_legacy(dev, &le_isa_params[i]) == 0) { - lesc->sc_rres = bus_alloc_resource_anywhere(dev, - SYS_RES_IOPORT, &j, - le_isa_params[i].iosize, RF_ACTIVE); - rap = le_isa_params[i].rap; - rdp = le_isa_params[i].rdp; - macstart = le_isa_params[i].macstart; - macstride = le_isa_params[i].macstride; - goto found; - } - } - /* FALLTHROUGH */ - case ENXIO: - default: - device_printf(dev, "cannot determine chip\n"); - error = ENXIO; - goto fail_mtx; - } - - found: - if (lesc->sc_rres == NULL) { - device_printf(dev, "cannot allocate registers\n"); - error = ENXIO; - goto fail_mtx; - } - lesc->sc_rap = rap; - lesc->sc_rdp = rdp; - - i = 0; - if ((lesc->sc_dres = bus_alloc_resource_any(dev, SYS_RES_DRQ, - &i, RF_ACTIVE)) == NULL) { - device_printf(dev, "cannot allocate DMA channel\n"); - error = ENXIO; - goto fail_rres; - } - - i = 0; - if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &i, RF_SHAREABLE | RF_ACTIVE)) == NULL) { - device_printf(dev, "cannot allocate interrupt\n"); - error = ENXIO; - goto fail_dres; - } - - error = bus_dma_tag_create( - bus_get_dma_tag(dev), /* parent */ - 1, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ - 0, /* nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &lesc->sc_pdmat); - if (error != 0) { - device_printf(dev, "cannot allocate parent DMA tag\n"); - goto fail_ires; - } - - sc->sc_memsize = LE_ISA_MEMSIZE; - /* - * For Am79C90, Am79C961 and Am79C961A the init block must be 2-byte - * aligned and the ring descriptors must be 8-byte aligned. - */ - error = bus_dma_tag_create( - lesc->sc_pdmat, /* parent */ - 8, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_24BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - sc->sc_memsize, /* maxsize */ - 1, /* nsegments */ - sc->sc_memsize, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &lesc->sc_dmat); - if (error != 0) { - device_printf(dev, "cannot allocate buffer DMA tag\n"); - goto fail_pdtag; - } - - error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, - BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); - if (error != 0) { - device_printf(dev, "cannot allocate DMA buffer memory\n"); - goto fail_dtag; - } - - sc->sc_addr = 0; - error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, - sc->sc_memsize, le_isa_dma_callback, sc, 0); - if (error != 0 || sc->sc_addr == 0) { - device_printf(dev, "cannot load DMA buffer map\n"); - goto fail_dmem; - } - - isa_dmacascade(rman_get_start(lesc->sc_dres)); - - sc->sc_flags = 0; - sc->sc_conf3 = 0; - - /* - * Extract the physical MAC address from the ROM. - */ - for (i = 0; i < sizeof(sc->sc_enaddr); i++) - sc->sc_enaddr[i] = bus_read_1(lesc->sc_rres, - macstart + i * macstride); - - sc->sc_copytodesc = lance_copytobuf_contig; - sc->sc_copyfromdesc = lance_copyfrombuf_contig; - sc->sc_copytobuf = lance_copytobuf_contig; - sc->sc_copyfrombuf = lance_copyfrombuf_contig; - sc->sc_zerobuf = lance_zerobuf_contig; - - sc->sc_rdcsr = le_isa_rdcsr; - sc->sc_wrcsr = le_isa_wrcsr; - sc->sc_hwreset = NULL; - sc->sc_hwinit = NULL; - sc->sc_hwintr = NULL; - sc->sc_nocarrier = NULL; - sc->sc_mediachange = NULL; - sc->sc_mediastatus = NULL; - sc->sc_supmedia = NULL; - - error = am7990_config(&lesc->sc_am7990, device_get_name(dev), - device_get_unit(dev)); - if (error != 0) { - device_printf(dev, "cannot attach Am7990\n"); - goto fail_dmap; - } - - error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, - NULL, am7990_intr, sc, &lesc->sc_ih); - if (error != 0) { - device_printf(dev, "cannot set up interrupt\n"); - goto fail_am7990; - } - - return (0); - - fail_am7990: - am7990_detach(&lesc->sc_am7990); - fail_dmap: - bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); - fail_dmem: - bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); - fail_dtag: - bus_dma_tag_destroy(lesc->sc_dmat); - fail_pdtag: - bus_dma_tag_destroy(lesc->sc_pdmat); - fail_ires: - bus_release_resource(dev, SYS_RES_IRQ, - rman_get_rid(lesc->sc_ires), lesc->sc_ires); - fail_dres: - bus_release_resource(dev, SYS_RES_DRQ, - rman_get_rid(lesc->sc_dres), lesc->sc_dres); - fail_rres: - bus_release_resource(dev, SYS_RES_IOPORT, - rman_get_rid(lesc->sc_rres), lesc->sc_rres); - fail_mtx: - LE_LOCK_DESTROY(sc); - return (error); -} - -static int -le_isa_detach(device_t dev) -{ - struct le_isa_softc *lesc; - struct lance_softc *sc; - - lesc = device_get_softc(dev); - sc = &lesc->sc_am7990.lsc; - - bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); - am7990_detach(&lesc->sc_am7990); - bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); - bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); - bus_dma_tag_destroy(lesc->sc_dmat); - bus_dma_tag_destroy(lesc->sc_pdmat); - bus_release_resource(dev, SYS_RES_IRQ, - rman_get_rid(lesc->sc_ires), lesc->sc_ires); - bus_release_resource(dev, SYS_RES_DRQ, - rman_get_rid(lesc->sc_dres), lesc->sc_dres); - bus_release_resource(dev, SYS_RES_IOPORT, - rman_get_rid(lesc->sc_rres), lesc->sc_rres); - LE_LOCK_DESTROY(sc); - - return (0); -} - -static int -le_isa_suspend(device_t dev) -{ - struct le_isa_softc *lesc; - - lesc = device_get_softc(dev); - - lance_suspend(&lesc->sc_am7990.lsc); - - return (0); -} - -static int -le_isa_resume(device_t dev) -{ - struct le_isa_softc *lesc; - - lesc = device_get_softc(dev); - - lance_resume(&lesc->sc_am7990.lsc); - - return (0); -} - -DEFINE_CLASS_0(le, le_isa_driver, le_isa_methods, sizeof(struct le_isa_softc)); -DRIVER_MODULE(le, isa, le_isa_driver, 0, 0); -MODULE_DEPEND(le, ether, 1, 1, 1); -ISA_PNP_INFO(le_isa_ids); diff --git a/sys/dev/le/if_le_pci.c b/sys/dev/le/if_le_pci.c deleted file mode 100644 index cee1e80295c9..000000000000 --- a/sys/dev/le/if_le_pci.c +++ /dev/null @@ -1,498 +0,0 @@ -/* $NetBSD: if_le_pci.c,v 1.43 2005/12/11 12:22:49 christos Exp $ */ - -/*- - * SPDX-License-Identifier: BSD-2-Clause AND BSD-3-Clause - * - * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace - * Simulation Facility, NASA Ames Research Center. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/systm.h> -#include <sys/bus.h> -#include <sys/endian.h> -#include <sys/kernel.h> -#include <sys/lock.h> -#include <sys/module.h> -#include <sys/mutex.h> -#include <sys/resource.h> -#include <sys/rman.h> -#include <sys/socket.h> - -#include <net/ethernet.h> -#include <net/if.h> -#include <net/if_media.h> - -#include <machine/bus.h> -#include <machine/resource.h> - -#include <dev/pci/pcireg.h> -#include <dev/pci/pcivar.h> - -#include <dev/le/lancereg.h> -#include <dev/le/lancevar.h> -#include <dev/le/am79900var.h> - -#define AMD_VENDOR 0x1022 -#define AMD_PCNET_PCI 0x2000 -#define AMD_PCNET_HOME 0x2001 -#define PCNET_MEMSIZE (32*1024) -#define PCNET_PCI_RDP 0x10 -#define PCNET_PCI_RAP 0x12 -#define PCNET_PCI_BDP 0x16 - -struct le_pci_softc { - struct am79900_softc sc_am79900; /* glue to MI code */ - - struct resource *sc_rres; - - struct resource *sc_ires; - void *sc_ih; - - bus_dma_tag_t sc_pdmat; - bus_dma_tag_t sc_dmat; - bus_dmamap_t sc_dmam; -}; - -static device_probe_t le_pci_probe; -static device_attach_t le_pci_attach; -static device_detach_t le_pci_detach; -static device_resume_t le_pci_resume; -static device_suspend_t le_pci_suspend; - -static device_method_t le_pci_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, le_pci_probe), - DEVMETHOD(device_attach, le_pci_attach), - DEVMETHOD(device_detach, le_pci_detach), - /* We can just use the suspend method here. */ - DEVMETHOD(device_shutdown, le_pci_suspend), - DEVMETHOD(device_suspend, le_pci_suspend), - DEVMETHOD(device_resume, le_pci_resume), - - { 0, 0 } -}; - -DEFINE_CLASS_0(le, le_pci_driver, le_pci_methods, sizeof(struct le_pci_softc)); -DRIVER_MODULE(le, pci, le_pci_driver, 0, 0); -MODULE_DEPEND(le, ether, 1, 1, 1); - -static const int le_home_supmedia[] = { - IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, 0) -}; - -static const int le_pci_supmedia[] = { - IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0), - IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, IFM_FDX, 0), - IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0), - IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, 0), - IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0), - IFM_MAKEWORD(IFM_ETHER, IFM_10_5, IFM_FDX, 0) -}; - -static void le_pci_wrbcr(struct lance_softc *, uint16_t, uint16_t); -static uint16_t le_pci_rdbcr(struct lance_softc *, uint16_t); -static void le_pci_wrcsr(struct lance_softc *, uint16_t, uint16_t); -static uint16_t le_pci_rdcsr(struct lance_softc *, uint16_t); -static int le_pci_mediachange(struct lance_softc *); -static void le_pci_hwreset(struct lance_softc *); -static bus_dmamap_callback_t le_pci_dma_callback; - -static void -le_pci_wrbcr(struct lance_softc *sc, uint16_t port, uint16_t val) -{ - struct le_pci_softc *lesc = (struct le_pci_softc *)sc; - - bus_write_2(lesc->sc_rres, PCNET_PCI_RAP, port); - bus_barrier(lesc->sc_rres, PCNET_PCI_RAP, 2, BUS_SPACE_BARRIER_WRITE); - bus_write_2(lesc->sc_rres, PCNET_PCI_BDP, val); -} - -static uint16_t -le_pci_rdbcr(struct lance_softc *sc, uint16_t port) -{ - struct le_pci_softc *lesc = (struct le_pci_softc *)sc; - - bus_write_2(lesc->sc_rres, PCNET_PCI_RAP, port); - bus_barrier(lesc->sc_rres, PCNET_PCI_RAP, 2, BUS_SPACE_BARRIER_WRITE); - return (bus_read_2(lesc->sc_rres, PCNET_PCI_BDP)); -} - -static void -le_pci_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) -{ - struct le_pci_softc *lesc = (struct le_pci_softc *)sc; - - bus_write_2(lesc->sc_rres, PCNET_PCI_RAP, port); - bus_barrier(lesc->sc_rres, PCNET_PCI_RAP, 2, BUS_SPACE_BARRIER_WRITE); - bus_write_2(lesc->sc_rres, PCNET_PCI_RDP, val); -} - -static uint16_t -le_pci_rdcsr(struct lance_softc *sc, uint16_t port) -{ - struct le_pci_softc *lesc = (struct le_pci_softc *)sc; - - bus_write_2(lesc->sc_rres, PCNET_PCI_RAP, port); - bus_barrier(lesc->sc_rres, PCNET_PCI_RAP, 2, BUS_SPACE_BARRIER_WRITE); - return (bus_read_2(lesc->sc_rres, PCNET_PCI_RDP)); -} - -static int -le_pci_mediachange(struct lance_softc *sc) -{ - struct ifmedia *ifm = &sc->sc_media; - uint16_t reg; - - if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) - return (EINVAL); - - if (IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) - le_pci_wrbcr(sc, LE_BCR49, - (le_pci_rdbcr(sc, LE_BCR49) & ~LE_B49_PHYSEL) | 0x1); - else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) - le_pci_wrbcr(sc, LE_BCR2, - le_pci_rdbcr(sc, LE_BCR2) | LE_B2_ASEL); - else { - le_pci_wrbcr(sc, LE_BCR2, - le_pci_rdbcr(sc, LE_BCR2) & ~LE_B2_ASEL); - - reg = le_pci_rdcsr(sc, LE_CSR15); - reg &= ~LE_C15_PORTSEL(LE_PORTSEL_MASK); - if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T) - reg |= LE_C15_PORTSEL(LE_PORTSEL_10T); - else - reg |= LE_C15_PORTSEL(LE_PORTSEL_AUI); - le_pci_wrcsr(sc, LE_CSR15, reg); - } - - reg = le_pci_rdbcr(sc, LE_BCR9); - if (IFM_OPTIONS(ifm->ifm_media) & IFM_FDX) { - reg |= LE_B9_FDEN; - /* - * Allow FDX on AUI only if explicitly chosen, - * not in autoselect mode. - */ - if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_5) - reg |= LE_B9_AUIFD; - else - reg &= ~LE_B9_AUIFD; - } else - reg &= ~LE_B9_FDEN; - le_pci_wrbcr(sc, LE_BCR9, reg); - - return (0); -} - -static void -le_pci_hwreset(struct lance_softc *sc) -{ - - /* - * Chip is stopped. Set software style to PCnet-PCI (32-bit). - * Actually, am79900.c implements ILACC support (hence its - * name) but unfortunately VMware does not. As far as this - * driver is concerned that should not make a difference - * though, as the settings used have the same meaning for - * both, ILACC and PCnet-PCI (note that there would be a - * difference for the ADD_FCS/NO_FCS bit if used). - */ - le_pci_wrbcr(sc, LE_BCR20, LE_B20_SSTYLE_PCNETPCI2); -} - -static void -le_pci_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) -{ - struct lance_softc *sc = (struct lance_softc *)xsc; - - if (error != 0) - return; - KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__)); - sc->sc_addr = segs[0].ds_addr; -} - -static int -le_pci_probe(device_t dev) -{ - - if (pci_get_vendor(dev) != AMD_VENDOR) - return (ENXIO); - - switch (pci_get_device(dev)) { - case AMD_PCNET_PCI: - device_set_desc(dev, "AMD PCnet-PCI"); - /* Let pcn(4) win. */ - return (BUS_PROBE_LOW_PRIORITY); - case AMD_PCNET_HOME: - device_set_desc(dev, "AMD PCnet-Home"); - /* Let pcn(4) win. */ - return (BUS_PROBE_LOW_PRIORITY); - default: - return (ENXIO); - } -} - -static int -le_pci_attach(device_t dev) -{ - struct le_pci_softc *lesc; - struct lance_softc *sc; - int error, i; - - lesc = device_get_softc(dev); - sc = &lesc->sc_am79900.lsc; - - LE_LOCK_INIT(sc, device_get_nameunit(dev)); - - pci_enable_busmaster(dev); - - i = PCIR_BAR(0); - lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT, - &i, RF_ACTIVE); - if (lesc->sc_rres == NULL) { - device_printf(dev, "cannot allocate registers\n"); - error = ENXIO; - goto fail_mtx; - } - - i = 0; - if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &i, RF_SHAREABLE | RF_ACTIVE)) == NULL) { - device_printf(dev, "cannot allocate interrupt\n"); - error = ENXIO; - goto fail_rres; - } - - error = bus_dma_tag_create( - bus_get_dma_tag(dev), /* parent */ - 1, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ - 0, /* nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &lesc->sc_pdmat); - if (error != 0) { - device_printf(dev, "cannot allocate parent DMA tag\n"); - goto fail_ires; - } - - sc->sc_memsize = PCNET_MEMSIZE; - /* - * For Am79C970A, Am79C971 and Am79C978 the init block must be 2-byte - * aligned and the ring descriptors must be 16-byte aligned when using - * a 32-bit software style. - */ - error = bus_dma_tag_create( - lesc->sc_pdmat, /* parent */ - 16, 0, /* alignment, boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - sc->sc_memsize, /* maxsize */ - 1, /* nsegments */ - sc->sc_memsize, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &lesc->sc_dmat); - if (error != 0) { - device_printf(dev, "cannot allocate buffer DMA tag\n"); - goto fail_pdtag; - } - - error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, - BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); - if (error != 0) { - device_printf(dev, "cannot allocate DMA buffer memory\n"); - goto fail_dtag; - } - - sc->sc_addr = 0; - error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, - sc->sc_memsize, le_pci_dma_callback, sc, 0); - if (error != 0 || sc->sc_addr == 0) { - device_printf(dev, "cannot load DMA buffer map\n"); - goto fail_dmem; - } - - sc->sc_flags = LE_BSWAP; - sc->sc_conf3 = 0; - - sc->sc_mediastatus = NULL; - switch (pci_get_device(dev)) { - case AMD_PCNET_HOME: - sc->sc_mediachange = le_pci_mediachange; - sc->sc_supmedia = le_home_supmedia; - sc->sc_nsupmedia = sizeof(le_home_supmedia) / sizeof(int); - sc->sc_defaultmedia = le_home_supmedia[0]; - break; - default: - sc->sc_mediachange = le_pci_mediachange; - sc->sc_supmedia = le_pci_supmedia; - sc->sc_nsupmedia = sizeof(le_pci_supmedia) / sizeof(int); - sc->sc_defaultmedia = le_pci_supmedia[0]; - } - - /* - * Extract the physical MAC address from the ROM. - */ - bus_read_region_1(lesc->sc_rres, 0, sc->sc_enaddr, - sizeof(sc->sc_enaddr)); - - sc->sc_copytodesc = lance_copytobuf_contig; - sc->sc_copyfromdesc = lance_copyfrombuf_contig; - sc->sc_copytobuf = lance_copytobuf_contig; - sc->sc_copyfrombuf = lance_copyfrombuf_contig; - sc->sc_zerobuf = lance_zerobuf_contig; - - sc->sc_rdcsr = le_pci_rdcsr; - sc->sc_wrcsr = le_pci_wrcsr; - sc->sc_hwreset = le_pci_hwreset; - sc->sc_hwinit = NULL; - sc->sc_hwintr = NULL; - sc->sc_nocarrier = NULL; - - error = am79900_config(&lesc->sc_am79900, device_get_name(dev), - device_get_unit(dev)); - if (error != 0) { - device_printf(dev, "cannot attach Am79900\n"); - goto fail_dmap; - } - - error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, - NULL, am79900_intr, sc, &lesc->sc_ih); - if (error != 0) { - device_printf(dev, "cannot set up interrupt\n"); - goto fail_am79900; - } - - return (0); - - fail_am79900: - am79900_detach(&lesc->sc_am79900); - fail_dmap: - bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); - fail_dmem: - bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); - fail_dtag: - bus_dma_tag_destroy(lesc->sc_dmat); - fail_pdtag: - bus_dma_tag_destroy(lesc->sc_pdmat); - fail_ires: - bus_release_resource(dev, SYS_RES_IRQ, - rman_get_rid(lesc->sc_ires), lesc->sc_ires); - fail_rres: - bus_release_resource(dev, SYS_RES_IOPORT, - rman_get_rid(lesc->sc_rres), lesc->sc_rres); - fail_mtx: - LE_LOCK_DESTROY(sc); - return (error); -} - -static int -le_pci_detach(device_t dev) -{ - struct le_pci_softc *lesc; - struct lance_softc *sc; - - lesc = device_get_softc(dev); - sc = &lesc->sc_am79900.lsc; - - bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); - am79900_detach(&lesc->sc_am79900); - bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); - bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); - bus_dma_tag_destroy(lesc->sc_dmat); - bus_dma_tag_destroy(lesc->sc_pdmat); - bus_release_resource(dev, SYS_RES_IRQ, - rman_get_rid(lesc->sc_ires), lesc->sc_ires); - bus_release_resource(dev, SYS_RES_IOPORT, - rman_get_rid(lesc->sc_rres), lesc->sc_rres); - LE_LOCK_DESTROY(sc); - - return (0); -} - -static int -le_pci_suspend(device_t dev) -{ - struct le_pci_softc *lesc; - - lesc = device_get_softc(dev); - - lance_suspend(&lesc->sc_am79900.lsc); - - return (0); -} - -static int -le_pci_resume(device_t dev) -{ - struct le_pci_softc *lesc; - - lesc = device_get_softc(dev); - - lance_resume(&lesc->sc_am79900.lsc); - - return (0); -} diff --git a/sys/dev/le/lance.c b/sys/dev/le/lance.c deleted file mode 100644 index df53242e80f4..000000000000 --- a/sys/dev/le/lance.c +++ /dev/null @@ -1,818 +0,0 @@ -/* $NetBSD: lance.c,v 1.34 2005/12/24 20:27:30 perry Exp $ */ - -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace - * Simulation Facility, NASA Ames Research Center. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <sys/param.h> -#include <sys/bus.h> -#include <sys/endian.h> -#include <sys/lock.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/mutex.h> -#include <sys/socket.h> -#include <sys/sockio.h> - -#include <net/ethernet.h> -#include <net/if.h> -#include <net/if_var.h> -#include <net/if_arp.h> -#include <net/if_dl.h> -#include <net/if_media.h> -#include <net/if_types.h> -#include <net/if_vlan_var.h> - -#include <machine/bus.h> - -#include <dev/le/lancereg.h> -#include <dev/le/lancevar.h> - -static void lance_start(if_t); -static void lance_stop(struct lance_softc *); -static void lance_init(void *); -static void lance_watchdog(void *s); -static int lance_mediachange(if_t); -static void lance_mediastatus(if_t, struct ifmediareq *); -static int lance_ioctl(if_t, u_long, caddr_t); - -int -lance_config(struct lance_softc *sc, const char* name, int unit) -{ - if_t ifp; - int i, nbuf; - - if (LE_LOCK_INITIALIZED(sc) == 0) - return (ENXIO); - - ifp = sc->sc_ifp = if_alloc(IFT_ETHER); - - callout_init_mtx(&sc->sc_wdog_ch, &sc->sc_mtx, 0); - - /* Initialize ifnet structure. */ - if_setsoftc(ifp, sc); - if_initname(ifp, name, unit); - if_setstartfn(ifp, lance_start); - if_setioctlfn(ifp, lance_ioctl); - if_setinitfn(ifp, lance_init); - if_setflags(ifp, IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); -#ifdef LANCE_REVC_BUG - if_setflagsbit(ifp, 0, IFF_MULTICAST); -#endif - if_setbaudrate(ifp, IF_Mbps(10)); - if_setsendqlen(ifp, ifqmaxlen); - if_setsendqready(ifp); - - /* Initialize ifmedia structures. */ - ifmedia_init(&sc->sc_media, 0, lance_mediachange, lance_mediastatus); - if (sc->sc_supmedia != NULL) { - for (i = 0; i < sc->sc_nsupmedia; i++) - ifmedia_add(&sc->sc_media, sc->sc_supmedia[i], 0, NULL); - ifmedia_set(&sc->sc_media, sc->sc_defaultmedia); - } else { - ifmedia_add(&sc->sc_media, - IFM_MAKEWORD(IFM_ETHER, IFM_MANUAL, 0, 0), 0, NULL); - ifmedia_set(&sc->sc_media, - IFM_MAKEWORD(IFM_ETHER, IFM_MANUAL, 0, 0)); - } - - switch (sc->sc_memsize) { - case 8192: - sc->sc_nrbuf = 4; - sc->sc_ntbuf = 1; - break; - case 16384: - sc->sc_nrbuf = 8; - sc->sc_ntbuf = 2; - break; - case 32768: - sc->sc_nrbuf = 16; - sc->sc_ntbuf = 4; - break; - case 65536: - sc->sc_nrbuf = 32; - sc->sc_ntbuf = 8; - break; - case 131072: - sc->sc_nrbuf = 64; - sc->sc_ntbuf = 16; - break; - case 262144: - sc->sc_nrbuf = 128; - sc->sc_ntbuf = 32; - break; - default: - /* weird memory size; cope with it */ - nbuf = sc->sc_memsize / LEBLEN; - sc->sc_ntbuf = nbuf / 5; - sc->sc_nrbuf = nbuf - sc->sc_ntbuf; - } - - if_printf(ifp, "%d receive buffers, %d transmit buffers\n", - sc->sc_nrbuf, sc->sc_ntbuf); - - /* Make sure the chip is stopped. */ - LE_LOCK(sc); - lance_stop(sc); - LE_UNLOCK(sc); - - return (0); -} - -void -lance_attach(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - - /* Attach the interface. */ - ether_ifattach(ifp, sc->sc_enaddr); - - /* Claim 802.1q capability. */ - if_setifheaderlen(ifp, sizeof(struct ether_vlan_header)); - if_setcapabilitiesbit(ifp, IFCAP_VLAN_MTU, 0); - if_setcapenablebit(ifp, IFCAP_VLAN_MTU, 0); - - gone_in(16, "Warning! le(4) to be removed: no longer needed for " - "Qemu/MIPS\n"); -} - -void -lance_detach(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - - LE_LOCK(sc); - lance_stop(sc); - LE_UNLOCK(sc); - callout_drain(&sc->sc_wdog_ch); - ether_ifdetach(ifp); - if_free(ifp); -} - -void -lance_suspend(struct lance_softc *sc) -{ - - LE_LOCK(sc); - lance_stop(sc); - LE_UNLOCK(sc); -} - -void -lance_resume(struct lance_softc *sc) -{ - - LE_LOCK(sc); - if (if_getflags(sc->sc_ifp) & IFF_UP) - lance_init_locked(sc); - LE_UNLOCK(sc); -} - -static void -lance_start(if_t ifp) -{ - struct lance_softc *sc = if_getsoftc(ifp); - - LE_LOCK(sc); - (*sc->sc_start_locked)(sc); - LE_UNLOCK(sc); -} - -static void -lance_stop(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - - LE_LOCK_ASSERT(sc, MA_OWNED); - - /* - * Mark the interface down and cancel the watchdog timer. - */ - if_setdrvflagbits(ifp, 0, (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)); - callout_stop(&sc->sc_wdog_ch); - sc->sc_wdog_timer = 0; - - (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); -} - -static void -lance_init(void *xsc) -{ - struct lance_softc *sc = (struct lance_softc *)xsc; - - LE_LOCK(sc); - lance_init_locked(sc); - LE_UNLOCK(sc); -} - -/* - * Initialization of interface; set up initialization block - * and transmit/receive descriptor rings. - */ -void -lance_init_locked(struct lance_softc *sc) -{ - if_t ifp = sc->sc_ifp; - u_long a; - int timo; - - LE_LOCK_ASSERT(sc, MA_OWNED); - - (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); - DELAY(100); - - /* Newer LANCE chips have a reset register. */ - if (sc->sc_hwreset) - (*sc->sc_hwreset)(sc); - - /* Set the correct byte swapping mode, etc. */ - (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3); - - /* Set the current media. This may require the chip to be stopped. */ - if (sc->sc_mediachange) - (void)(*sc->sc_mediachange)(sc); - - /* - * Update our private copy of the Ethernet address. - * We NEED the copy so we can ensure its alignment! - */ - memcpy(sc->sc_enaddr, if_getlladdr(ifp), ETHER_ADDR_LEN); - - /* Set up LANCE init block. */ - (*sc->sc_meminit)(sc); - - /* Give LANCE the physical address of its init block. */ - a = sc->sc_addr + LE_INITADDR(sc); - (*sc->sc_wrcsr)(sc, LE_CSR1, a & 0xffff); - (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16); - - /* Try to initialize the LANCE. */ - DELAY(100); - (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT); - - /* Wait for initialization to finish. */ - for (timo = 100000; timo; timo--) - if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) - break; - - if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) { - /* Start the LANCE. */ - (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT); - if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); - if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); - sc->sc_wdog_timer = 0; - callout_reset(&sc->sc_wdog_ch, hz, lance_watchdog, sc); - (*sc->sc_start_locked)(sc); - } else - if_printf(ifp, "controller failed to initialize\n"); - - if (sc->sc_hwinit) - (*sc->sc_hwinit)(sc); -} - -/* - * Routine to copy from mbuf chain to transmit buffer in - * network buffer memory. - */ -int -lance_put(struct lance_softc *sc, int boff, struct mbuf *m) -{ - struct mbuf *n; - int len, tlen = 0; - - LE_LOCK_ASSERT(sc, MA_OWNED); - - for (; m; m = n) { - len = m->m_len; - if (len == 0) { - n = m_free(m); - m = NULL; - continue; - } - (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len); - boff += len; - tlen += len; - n = m_free(m); - m = NULL; - } - if (tlen < LEMINSIZE) { - (*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen); - tlen = LEMINSIZE; - } - return (tlen); -} - -/* - * Pull data off an interface. - * Len is length of data, with local net header stripped. - * We copy the data into mbufs. When full cluster sized units are present - * we copy into clusters. - */ -struct mbuf * -lance_get(struct lance_softc *sc, int boff, int totlen) -{ - if_t ifp = sc->sc_ifp; - struct mbuf *m, *m0, *newm; - caddr_t newdata; - int len; - - if (totlen <= ETHER_HDR_LEN || totlen > LEBLEN - ETHER_CRC_LEN) { -#ifdef LEDEBUG - if_printf(ifp, "invalid packet size %d; dropping\n", totlen); -#endif - return (NULL); - } - - MGETHDR(m0, M_NOWAIT, MT_DATA); - if (m0 == NULL) - return (NULL); - m0->m_pkthdr.rcvif = ifp; - m0->m_pkthdr.len = totlen; - len = MHLEN; - m = m0; - - while (totlen > 0) { - if (totlen >= MINCLSIZE) { - if (!(MCLGET(m, M_NOWAIT))) - goto bad; - len = MCLBYTES; - } - - if (m == m0) { - newdata = (caddr_t) - ALIGN(m->m_data + ETHER_HDR_LEN) - ETHER_HDR_LEN; - len -= newdata - m->m_data; - m->m_data = newdata; - } - - m->m_len = len = min(totlen, len); - (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len); - boff += len; - - totlen -= len; - if (totlen > 0) { - MGET(newm, M_NOWAIT, MT_DATA); - if (newm == NULL) - goto bad; - len = MLEN; - m = m->m_next = newm; - } - } - - return (m0); - - bad: - m_freem(m0); - return (NULL); -} - -static void -lance_watchdog(void *xsc) -{ - struct lance_softc *sc = (struct lance_softc *)xsc; - if_t ifp = sc->sc_ifp; - - LE_LOCK_ASSERT(sc, MA_OWNED); - - if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) { - callout_reset(&sc->sc_wdog_ch, hz, lance_watchdog, sc); - return; - } - - if_printf(ifp, "device timeout\n"); - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); - lance_init_locked(sc); -} - -static int -lance_mediachange(if_t ifp) -{ - struct lance_softc *sc = if_getsoftc(ifp); - - if (sc->sc_mediachange) { - /* - * For setting the port in LE_CSR15 the PCnet chips must - * be powered down or stopped and unlike documented may - * not take effect without an initialization. So don't - * invoke (*sc_mediachange) directly here but go through - * lance_init_locked(). - */ - LE_LOCK(sc); - lance_stop(sc); - lance_init_locked(sc); - if (!if_sendq_empty(ifp)) - (*sc->sc_start_locked)(sc); - LE_UNLOCK(sc); - } - return (0); -} - -static void -lance_mediastatus(if_t ifp, struct ifmediareq *ifmr) -{ - struct lance_softc *sc = if_getsoftc(ifp); - - LE_LOCK(sc); - if (!(if_getflags(ifp) & IFF_UP)) { - LE_UNLOCK(sc); - return; - } - - ifmr->ifm_status = IFM_AVALID; - if (sc->sc_flags & LE_CARRIER) - ifmr->ifm_status |= IFM_ACTIVE; - - if (sc->sc_mediastatus) - (*sc->sc_mediastatus)(sc, ifmr); - LE_UNLOCK(sc); -} - -/* - * Process an ioctl request. - */ -static int -lance_ioctl(if_t ifp, u_long cmd, caddr_t data) -{ - struct lance_softc *sc = if_getsoftc(ifp); - struct ifreq *ifr = (struct ifreq *)data; - int error = 0; - - switch (cmd) { - case SIOCSIFFLAGS: - LE_LOCK(sc); - if (if_getflags(ifp) & IFF_PROMISC) { - if (!(sc->sc_flags & LE_PROMISC)) { - sc->sc_flags |= LE_PROMISC; - lance_init_locked(sc); - } - } else if (sc->sc_flags & LE_PROMISC) { - sc->sc_flags &= ~LE_PROMISC; - lance_init_locked(sc); - } - - if ((if_getflags(ifp) & IFF_ALLMULTI) && - !(sc->sc_flags & LE_ALLMULTI)) { - sc->sc_flags |= LE_ALLMULTI; - lance_init_locked(sc); - } else if (!(if_getflags(ifp) & IFF_ALLMULTI) && - (sc->sc_flags & LE_ALLMULTI)) { - sc->sc_flags &= ~LE_ALLMULTI; - lance_init_locked(sc); - } - - if (!(if_getflags(ifp) & IFF_UP) && - if_getdrvflags(ifp) & IFF_DRV_RUNNING) { - /* - * If interface is marked down and it is running, then - * stop it. - */ - lance_stop(sc); - } else if (if_getflags(ifp) & IFF_UP && - !(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) { - /* - * If interface is marked up and it is stopped, then - * start it. - */ - lance_init_locked(sc); - } -#ifdef LEDEBUG - if (if_getflags(ifp) & IFF_DEBUG) - sc->sc_flags |= LE_DEBUG; - else - sc->sc_flags &= ~LE_DEBUG; -#endif - LE_UNLOCK(sc); - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - /* - * Multicast list has changed; set the hardware filter - * accordingly. - */ - LE_LOCK(sc); - if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) - lance_init_locked(sc); - LE_UNLOCK(sc); - break; - - case SIOCGIFMEDIA: - case SIOCSIFMEDIA: - error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); - break; - - default: - error = ether_ioctl(ifp, cmd, data); - break; - } - - return (error); -} - -struct lance_hash_maddr_ctx { - struct lance_softc *sc; - uint16_t *af; -}; - -static u_int -lance_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) -{ - struct lance_hash_maddr_ctx *ctx = arg; - struct lance_softc *sc = ctx->sc; - uint32_t crc; - - crc = ether_crc32_le(LLADDR(sdl), ETHER_ADDR_LEN); - /* Just want the 6 most significant bits. */ - crc >>= 26; - /* Set the corresponding bit in the filter. */ - ctx->af[crc >> 4] |= LE_HTOLE16(1 << (crc & 0xf)); - - return (1); -} - -/* - * Set up the logical address filter. - */ -void -lance_setladrf(struct lance_softc *sc, uint16_t *af) -{ - if_t ifp = sc->sc_ifp; - struct lance_hash_maddr_ctx ctx = { sc, af }; - - /* - * Set up multicast address filter by passing all multicast addresses - * through a crc generator, and then using the high order 6 bits as an - * index into the 64 bit logical address filter. The high order bit - * selects the word, while the rest of the bits select the bit within - * the word. - */ - - if (if_getflags(ifp) & IFF_PROMISC || sc->sc_flags & LE_ALLMULTI) { - af[0] = af[1] = af[2] = af[3] = 0xffff; - return; - } - - af[0] = af[1] = af[2] = af[3] = 0x0000; - if_foreach_llmaddr(ifp, lance_hash_maddr, &ctx); -} - -/* - * Routines for accessing the transmit and receive buffers. - * The various CPU and adapter configurations supported by this - * driver require three different access methods for buffers - * and descriptors: - * (1) contig (contiguous data; no padding), - * (2) gap2 (two bytes of data followed by two bytes of padding), - * (3) gap16 (16 bytes of data followed by 16 bytes of padding). - */ - -/* - * contig: contiguous data with no padding. - * - * Buffers may have any alignment. - */ - -void -lance_copytobuf_contig(struct lance_softc *sc, void *from, int boff, int len) -{ - volatile caddr_t buf = sc->sc_mem; - - /* - * Just call memcpy() to do the work. - */ - memcpy(buf + boff, from, len); -} - -void -lance_copyfrombuf_contig(struct lance_softc *sc, void *to, int boff, int len) -{ - volatile caddr_t buf = sc->sc_mem; - - /* - * Just call memcpy() to do the work. - */ - memcpy(to, buf + boff, len); -} - -void -lance_zerobuf_contig(struct lance_softc *sc, int boff, int len) -{ - volatile caddr_t buf = sc->sc_mem; - - /* - * Just let memset() do the work - */ - memset(buf + boff, 0, len); -} - -#if 0 -/* - * Examples only; duplicate these and tweak (if necessary) in - * machine-specific front-ends. - */ - -/* - * gap2: two bytes of data followed by two bytes of pad. - * - * Buffers must be 4-byte aligned. The code doesn't worry about - * doing an extra byte. - */ - -static void -lance_copytobuf_gap2(struct lance_softc *sc, void *fromv, int boff, int len) -{ - volatile caddr_t buf = sc->sc_mem; - caddr_t from = fromv; - volatile uint16_t *bptr; - - if (boff & 0x1) { - /* Handle unaligned first byte. */ - bptr = ((volatile uint16_t *)buf) + (boff - 1); - *bptr = (*from++ << 8) | (*bptr & 0xff); - bptr += 2; - len--; - } else - bptr = ((volatile uint16_t *)buf) + boff; - while (len > 1) { - *bptr = (from[1] << 8) | (from[0] & 0xff); - bptr += 2; - from += 2; - len -= 2; - } - if (len == 1) - *bptr = (uint16_t)*from; -} - -static void -lance_copyfrombuf_gap2(struct lance_softc *sc, void *tov, int boff, int len) -{ - volatile caddr_t buf = sc->sc_mem; - caddr_t to = tov; - volatile uint16_t *bptr; - uint16_t tmp; - - if (boff & 0x1) { - /* Handle unaligned first byte. */ - bptr = ((volatile uint16_t *)buf) + (boff - 1); - *to++ = (*bptr >> 8) & 0xff; - bptr += 2; - len--; - } else - bptr = ((volatile uint16_t *)buf) + boff; - while (len > 1) { - tmp = *bptr; - *to++ = tmp & 0xff; - *to++ = (tmp >> 8) & 0xff; - bptr += 2; - len -= 2; - } - if (len == 1) - *to = *bptr & 0xff; -} - -static void -lance_zerobuf_gap2(struct lance_softc *sc, int boff, int len) -{ - volatile caddr_t buf = sc->sc_mem; - volatile uint16_t *bptr; - - if ((unsigned)boff & 0x1) { - bptr = ((volatile uint16_t *)buf) + (boff - 1); - *bptr &= 0xff; - bptr += 2; - len--; - } else - bptr = ((volatile uint16_t *)buf) + boff; - while (len > 0) { - *bptr = 0; - bptr += 2; - len -= 2; - } -} - -/* - * gap16: 16 bytes of data followed by 16 bytes of pad. - * - * Buffers must be 32-byte aligned. - */ - -static void -lance_copytobuf_gap16(struct lance_softc *sc, void *fromv, int boff, int len) -{ - volatile caddr_t buf = sc->sc_mem; - caddr_t bptr, from = fromv; - int xfer; - - bptr = buf + ((boff << 1) & ~0x1f); - boff &= 0xf; - xfer = min(len, 16 - boff); - while (len > 0) { - memcpy(bptr + boff, from, xfer); - from += xfer; - bptr += 32; - boff = 0; - len -= xfer; - xfer = min(len, 16); - } -} - -static void -lance_copyfrombuf_gap16(struct lance_softc *sc, void *tov, int boff, int len) -{ - volatile caddr_t buf = sc->sc_mem; - caddr_t bptr, to = tov; - int xfer; - - bptr = buf + ((boff << 1) & ~0x1f); - boff &= 0xf; - xfer = min(len, 16 - boff); - while (len > 0) { - memcpy(to, bptr + boff, xfer); - to += xfer; - bptr += 32; - boff = 0; - len -= xfer; - xfer = min(len, 16); - } -} - -static void -lance_zerobuf_gap16(struct lance_softc *sc, int boff, int len) -{ - volatile caddr_t buf = sc->sc_mem; - caddr_t bptr; - int xfer; - - bptr = buf + ((boff << 1) & ~0x1f); - boff &= 0xf; - xfer = min(len, 16 - boff); - while (len > 0) { - memset(bptr + boff, 0, xfer); - bptr += 32; - boff = 0; - len -= xfer; - xfer = min(len, 16); - } -} -#endif /* Example only */ diff --git a/sys/dev/le/lancereg.h b/sys/dev/le/lancereg.h deleted file mode 100644 index f0d5698a25c5..000000000000 --- a/sys/dev/le/lancereg.h +++ /dev/null @@ -1,611 +0,0 @@ -/* $NetBSD: lancereg.h,v 1.12 2005/12/11 12:21:27 christos Exp $ */ - -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum and Jason R. Thorpe. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/*- - * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Ralph Campbell and Rick Macklem. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* - * Register description for the following Advanced Micro Devices - * Ethernet chips: - * - * - Am7990 Local Area Network Controller for Ethernet (LANCE) - * (and its descendent Am79c90 C-LANCE). - * - * - Am79c900 Integrated Local Area Communications Controller (ILACC) - * - * - Am79c960 PCnet-ISA Single-Chip Ethernet Controller for ISA - * - * - Am79c961 PCnet-ISA+ Jumperless Single-Chip Ethernet Controller - * for ISA - * - * - Am79c961A PCnet-ISA II Jumperless Full-Duplex Single-Chip - * Ethernet Controller for ISA - * - * - Am79c965A PCnet-32 Single-Chip 32-bit Ethernet Controller - * (for VESA and 486 local busses) - * - * - Am79c970 PCnet-PCI Single-Chip Ethernet Controller for PCI - * Local Bus - * - * - Am79c970A PCnet-PCI II Single-Chip Full-Duplex Ethernet Controller - * for PCI Local Bus - * - * - Am79c971 PCnet-FAST Single-Chip Full-Duplex 10/100Mbps - * Ethernet Controller for PCI Local Bus - * - * - Am79c972 PCnet-FAST+ Enhanced 10/100Mbps PCI Ethernet Controller - * with OnNow Support - * - * - Am79c973/Am79c975 PCnet-FAST III Single-Chip 10/100Mbps PCI - * Ethernet Controller with Integrated PHY - * - * - Am79c978 PCnet-Home Single-Chip 1/10 Mbps PCI Home - * Networking Controller. - * - * Initialization block, transmit descriptor, and receive descriptor - * formats are described in two separate files: - * - * 16-bit software model (LANCE) am7990reg.h - * - * 32-bit software model (ILACC) am79900reg.h - * - * Note that the vast majority of the registers described in this file - * belong to follow-on chips to the original LANCE. Only CSR0-CSR3 are - * valid on the LANCE. - */ - - -#ifndef _DEV_LE_LANCEREG_H_ -#define _DEV_LE_LANCEREG_H_ - -#define LEBLEN (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) -/* LEMINSIZE should be ETHER_MIN_LEN when LE_MODE_DTCR is set. */ -#define LEMINSIZE (ETHER_MIN_LEN - ETHER_CRC_LEN) - -#define LE_INITADDR(sc) (sc->sc_initaddr) -#define LE_RMDADDR(sc, bix) (sc->sc_rmdaddr + sizeof(struct lermd) * (bix)) -#define LE_TMDADDR(sc, bix) (sc->sc_tmdaddr + sizeof(struct letmd) * (bix)) -#define LE_RBUFADDR(sc, bix) (sc->sc_rbufaddr + LEBLEN * (bix)) -#define LE_TBUFADDR(sc, bix) (sc->sc_tbufaddr + LEBLEN * (bix)) - -/* - * The byte count fields in descriptors are in two's complement. - * This macro does the conversion for us on unsigned numbers. - */ -#define LE_BCNT(x) (~(x) + 1) - -/* - * Control and Status Register addresses - */ -#define LE_CSR0 0x0000 /* Control and status register */ -#define LE_CSR1 0x0001 /* low address of init block */ -#define LE_CSR2 0x0002 /* high address of init block */ -#define LE_CSR3 0x0003 /* Bus master and control */ -#define LE_CSR4 0x0004 /* Test and features control */ -#define LE_CSR5 0x0005 /* Extended control and Interrupt 1 */ -#define LE_CSR6 0x0006 /* Rx/Tx Descriptor table length */ -#define LE_CSR7 0x0007 /* Extended control and interrupt 2 */ -#define LE_CSR8 0x0008 /* Logical Address Filter 0 */ -#define LE_CSR9 0x0009 /* Logical Address Filter 1 */ -#define LE_CSR10 0x000a /* Logical Address Filter 2 */ -#define LE_CSR11 0x000b /* Logical Address Filter 3 */ -#define LE_CSR12 0x000c /* Physical Address 0 */ -#define LE_CSR13 0x000d /* Physical Address 1 */ -#define LE_CSR14 0x000e /* Physical Address 2 */ -#define LE_CSR15 0x000f /* Mode */ -#define LE_CSR16 0x0010 /* Initialization Block addr lower */ -#define LE_CSR17 0x0011 /* Initialization Block addr upper */ -#define LE_CSR18 0x0012 /* Current Rx Buffer addr lower */ -#define LE_CSR19 0x0013 /* Current Rx Buffer addr upper */ -#define LE_CSR20 0x0014 /* Current Tx Buffer addr lower */ -#define LE_CSR21 0x0015 /* Current Tx Buffer addr upper */ -#define LE_CSR22 0x0016 /* Next Rx Buffer addr lower */ -#define LE_CSR23 0x0017 /* Next Rx Buffer addr upper */ -#define LE_CSR24 0x0018 /* Base addr of Rx ring lower */ -#define LE_CSR25 0x0019 /* Base addr of Rx ring upper */ -#define LE_CSR26 0x001a /* Next Rx Desc addr lower */ -#define LE_CSR27 0x001b /* Next Rx Desc addr upper */ -#define LE_CSR28 0x001c /* Current Rx Desc addr lower */ -#define LE_CSR29 0x001d /* Current Rx Desc addr upper */ -#define LE_CSR30 0x001e /* Base addr of Tx ring lower */ -#define LE_CSR31 0x001f /* Base addr of Tx ring upper */ -#define LE_CSR32 0x0020 /* Next Tx Desc addr lower */ -#define LE_CSR33 0x0021 /* Next Tx Desc addr upper */ -#define LE_CSR34 0x0022 /* Current Tx Desc addr lower */ -#define LE_CSR35 0x0023 /* Current Tx Desc addr upper */ -#define LE_CSR36 0x0024 /* Next Next Rx Desc addr lower */ -#define LE_CSR37 0x0025 /* Next Next Rx Desc addr upper */ -#define LE_CSR38 0x0026 /* Next Next Tx Desc addr lower */ -#define LE_CSR39 0x0027 /* Next Next Tx Desc adddr upper */ -#define LE_CSR40 0x0028 /* Current Rx Byte Count */ -#define LE_CSR41 0x0029 /* Current Rx Status */ -#define LE_CSR42 0x002a /* Current Tx Byte Count */ -#define LE_CSR43 0x002b /* Current Tx Status */ -#define LE_CSR44 0x002c /* Next Rx Byte Count */ -#define LE_CSR45 0x002d /* Next Rx Status */ -#define LE_CSR46 0x002e /* Tx Poll Time Counter */ -#define LE_CSR47 0x002f /* Tx Polling Interval */ -#define LE_CSR48 0x0030 /* Rx Poll Time Counter */ -#define LE_CSR49 0x0031 /* Rx Polling Interval */ -#define LE_CSR58 0x003a /* Software Style */ -#define LE_CSR60 0x003c /* Previous Tx Desc addr lower */ -#define LE_CSR61 0x003d /* Previous Tx Desc addr upper */ -#define LE_CSR62 0x003e /* Previous Tx Byte Count */ -#define LE_CSR63 0x003f /* Previous Tx Status */ -#define LE_CSR64 0x0040 /* Next Tx Buffer addr lower */ -#define LE_CSR65 0x0041 /* Next Tx Buffer addr upper */ -#define LE_CSR66 0x0042 /* Next Tx Byte Count */ -#define LE_CSR67 0x0043 /* Next Tx Status */ -#define LE_CSR72 0x0048 /* Receive Ring Counter */ -#define LE_CSR74 0x004a /* Transmit Ring Counter */ -#define LE_CSR76 0x004c /* Receive Ring Length */ -#define LE_CSR78 0x004e /* Transmit Ring Length */ -#define LE_CSR80 0x0050 /* DMA Transfer Counter and FIFO - Threshold Control */ -#define LE_CSR82 0x0052 /* Tx Desc addr Pointer lower */ -#define LE_CSR84 0x0054 /* DMA addr register lower */ -#define LE_CSR85 0x0055 /* DMA addr register upper */ -#define LE_CSR86 0x0056 /* Buffer Byte Counter */ -#define LE_CSR88 0x0058 /* Chip ID Register lower */ -#define LE_CSR89 0x0059 /* Chip ID Register upper */ -#define LE_CSR92 0x005c /* Ring Length Conversion */ -#define LE_CSR100 0x0064 /* Bus Timeout */ -#define LE_CSR112 0x0070 /* Missed Frame Count */ -#define LE_CSR114 0x0072 /* Receive Collision Count */ -#define LE_CSR116 0x0074 /* OnNow Power Mode Register */ -#define LE_CSR122 0x007a /* Advanced Feature Control */ -#define LE_CSR124 0x007c /* Test Register 1 */ -#define LE_CSR125 0x007d /* MAC Enhanced Configuration Control */ - -/* - * Bus Configuration Register addresses - */ -#define LE_BCR0 0x0000 /* Master Mode Read Active */ -#define LE_BCR1 0x0001 /* Master Mode Write Active */ -#define LE_BCR2 0x0002 /* Misc. Configuration */ -#define LE_BCR4 0x0004 /* LED0 Status */ -#define LE_BCR5 0x0005 /* LED1 Status */ -#define LE_BCR6 0x0006 /* LED2 Status */ -#define LE_BCR7 0x0007 /* LED3 Status */ -#define LE_BCR9 0x0009 /* Full-duplex Control */ -#define LE_BCR16 0x0010 /* I/O Base Address lower */ -#define LE_BCR17 0x0011 /* I/O Base Address upper */ -#define LE_BCR18 0x0012 /* Burst and Bus Control Register */ -#define LE_BCR19 0x0013 /* EEPROM Control and Status */ -#define LE_BCR20 0x0014 /* Software Style */ -#define LE_BCR22 0x0016 /* PCI Latency Register */ -#define LE_BCR23 0x0017 /* PCI Subsystem Vendor ID */ -#define LE_BCR24 0x0018 /* PCI Subsystem ID */ -#define LE_BCR25 0x0019 /* SRAM Size Register */ -#define LE_BCR26 0x001a /* SRAM Boundary Register */ -#define LE_BCR27 0x001b /* SRAM Interface Control Register */ -#define LE_BCR28 0x001c /* Exp. Bus Port Addr lower */ -#define LE_BCR29 0x001d /* Exp. Bus Port Addr upper */ -#define LE_BCR30 0x001e /* Exp. Bus Data Port */ -#define LE_BCR31 0x001f /* Software Timer Register */ -#define LE_BCR32 0x0020 /* PHY Control and Status Register */ -#define LE_BCR33 0x0021 /* PHY Address Register */ -#define LE_BCR34 0x0022 /* PHY Management Data Register */ -#define LE_BCR35 0x0023 /* PCI Vendor ID Register */ -#define LE_BCR36 0x0024 /* PCI Power Management Cap. Alias */ -#define LE_BCR37 0x0025 /* PCI DATA0 Alias */ -#define LE_BCR38 0x0026 /* PCI DATA1 Alias */ -#define LE_BCR39 0x0027 /* PCI DATA2 Alias */ -#define LE_BCR40 0x0028 /* PCI DATA3 Alias */ -#define LE_BCR41 0x0029 /* PCI DATA4 Alias */ -#define LE_BCR42 0x002a /* PCI DATA5 Alias */ -#define LE_BCR43 0x002b /* PCI DATA6 Alias */ -#define LE_BCR44 0x002c /* PCI DATA7 Alias */ -#define LE_BCR45 0x002d /* OnNow Pattern Matching 1 */ -#define LE_BCR46 0x002e /* OnNow Pattern Matching 2 */ -#define LE_BCR47 0x002f /* OnNow Pattern Matching 3 */ -#define LE_BCR48 0x0030 /* LED4 Status */ -#define LE_BCR49 0x0031 /* PHY Select */ - -/* Control and status register 0 (csr0) */ -#define LE_C0_ERR 0x8000 /* error summary */ -#define LE_C0_BABL 0x4000 /* transmitter timeout error */ -#define LE_C0_CERR 0x2000 /* collision */ -#define LE_C0_MISS 0x1000 /* missed a packet */ -#define LE_C0_MERR 0x0800 /* memory error */ -#define LE_C0_RINT 0x0400 /* receiver interrupt */ -#define LE_C0_TINT 0x0200 /* transmitter interrupt */ -#define LE_C0_IDON 0x0100 /* initialization done */ -#define LE_C0_INTR 0x0080 /* interrupt condition */ -#define LE_C0_INEA 0x0040 /* interrupt enable */ -#define LE_C0_RXON 0x0020 /* receiver on */ -#define LE_C0_TXON 0x0010 /* transmitter on */ -#define LE_C0_TDMD 0x0008 /* transmit demand */ -#define LE_C0_STOP 0x0004 /* disable all external activity */ -#define LE_C0_STRT 0x0002 /* enable external activity */ -#define LE_C0_INIT 0x0001 /* begin initialization */ - -#define LE_C0_BITS \ - "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\ -\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT" - -/* Control and status register 3 (csr3) */ -#define LE_C3_BABLM 0x4000 /* babble mask */ -#define LE_C3_MISSM 0x1000 /* missed frame mask */ -#define LE_C3_MERRM 0x0800 /* memory error mask */ -#define LE_C3_RINTM 0x0400 /* receive interrupt mask */ -#define LE_C3_TINTM 0x0200 /* transmit interrupt mask */ -#define LE_C3_IDONM 0x0100 /* initialization done mask */ -#define LE_C3_DXSUFLO 0x0040 /* disable tx stop on underflow */ -#define LE_C3_LAPPEN 0x0020 /* look ahead packet processing enbl */ -#define LE_C3_DXMT2PD 0x0010 /* disable tx two part deferral */ -#define LE_C3_EMBA 0x0008 /* enable modified backoff algorithm */ -#define LE_C3_BSWP 0x0004 /* byte swap */ -#define LE_C3_ACON 0x0002 /* ALE control, eh? */ -#define LE_C3_BCON 0x0001 /* byte control */ - -/* Control and status register 4 (csr4) */ -#define LE_C4_EN124 0x8000 /* enable CSR124 */ -#define LE_C4_DMAPLUS 0x4000 /* always set (PCnet-PCI) */ -#define LE_C4_TIMER 0x2000 /* enable bus activity timer */ -#define LE_C4_TXDPOLL 0x1000 /* disable transmit polling */ -#define LE_C4_APAD_XMT 0x0800 /* auto pad transmit */ -#define LE_C4_ASTRP_RCV 0x0400 /* auto strip receive */ -#define LE_C4_MFCO 0x0200 /* missed frame counter overflow */ -#define LE_C4_MFCOM 0x0100 /* missed frame coutner overflow mask */ -#define LE_C4_UINTCMD 0x0080 /* user interrupt command */ -#define LE_C4_UINT 0x0040 /* user interrupt */ -#define LE_C4_RCVCCO 0x0020 /* receive collision counter overflow */ -#define LE_C4_RCVCCOM 0x0010 /* receive collision counter overflow - mask */ -#define LE_C4_TXSTRT 0x0008 /* transmit start status */ -#define LE_C4_TXSTRTM 0x0004 /* transmit start mask */ - -/* Control and status register 5 (csr5) */ -#define LE_C5_TOKINTD 0x8000 /* transmit ok interrupt disable */ -#define LE_C5_LTINTEN 0x4000 /* last transmit interrupt enable */ -#define LE_C5_SINT 0x0800 /* system interrupt */ -#define LE_C5_SINTE 0x0400 /* system interrupt enable */ -#define LE_C5_EXDINT 0x0080 /* excessive deferral interrupt */ -#define LE_C5_EXDINTE 0x0040 /* excessive deferral interrupt enbl */ -#define LE_C5_MPPLBA 0x0020 /* magic packet physical logical - broadcast accept */ -#define LE_C5_MPINT 0x0010 /* magic packet interrupt */ -#define LE_C5_MPINTE 0x0008 /* magic packet interrupt enable */ -#define LE_C5_MPEN 0x0004 /* magic packet enable */ -#define LE_C5_MPMODE 0x0002 /* magic packet mode */ -#define LE_C5_SPND 0x0001 /* suspend */ - -/* Control and status register 6 (csr6) */ -#define LE_C6_TLEN 0xf000 /* TLEN from init block */ -#define LE_C6_RLEN 0x0f00 /* RLEN from init block */ - -/* Control and status register 7 (csr7) */ -#define LE_C7_FASTSPNDE 0x8000 /* fast suspend enable */ -#define LE_C7_RDMD 0x2000 /* receive demand */ -#define LE_C7_RDXPOLL 0x1000 /* receive disable polling */ -#define LE_C7_STINT 0x0800 /* software timer interrupt */ -#define LE_C7_STINTE 0x0400 /* software timer interrupt enable */ -#define LE_C7_MREINT 0x0200 /* PHY management read error intr */ -#define LE_C7_MREINTE 0x0100 /* PHY management read error intr - enable */ -#define LE_C7_MAPINT 0x0080 /* PHY management auto-poll intr */ -#define LE_C7_MAPINTE 0x0040 /* PHY management auto-poll intr - enable */ -#define LE_C7_MCCINT 0x0020 /* PHY management command complete - interrupt */ -#define LE_C7_MCCINTE 0x0010 /* PHY management command complete - interrupt enable */ -#define LE_C7_MCCIINT 0x0008 /* PHY management command complete - internal interrupt */ -#define LE_C7_MCCIINTE 0x0004 /* PHY management command complete - internal interrupt enable */ -#define LE_C7_MIIPDTINT 0x0002 /* PHY management detect transition - interrupt */ -#define LE_C7_MIIPDTINTE 0x0001 /* PHY management detect transition - interrupt enable */ - -/* Control and status register 15 (csr15) */ -#define LE_C15_PROM 0x8000 /* promiscuous mode */ -#define LE_C15_DRCVBC 0x4000 /* disable Rx of broadcast */ -#define LE_C15_DRCVPA 0x2000 /* disable Rx of physical address */ -#define LE_C15_DLNKTST 0x1000 /* disable link status */ -#define LE_C15_DAPC 0x0800 /* disable auto-polarity correction */ -#define LE_C15_MENDECL 0x0400 /* MENDEC Loopback mode */ -#define LE_C15_LRT 0x0200 /* low receive threshold (TMAU) */ -#define LE_C15_TSEL 0x0200 /* transmit mode select (AUI) */ -#define LE_C15_PORTSEL(x) ((x) << 7) /* port select */ -#define LE_C15_INTL 0x0040 /* internal loopback */ -#define LE_C15_DRTY 0x0020 /* disable retry */ -#define LE_C15_FCOLL 0x0010 /* force collision */ -#define LE_C15_DXMTFCS 0x0008 /* disable Tx FCS (ADD_FCS overrides) */ -#define LE_C15_LOOP 0x0004 /* loopback enable */ -#define LE_C15_DTX 0x0002 /* disable transmit */ -#define LE_C15_DRX 0x0001 /* disable receiver */ - -#define LE_PORTSEL_AUI 0 -#define LE_PORTSEL_10T 1 -#define LE_PORTSEL_GPSI 2 -#define LE_PORTSEL_MII 3 -#define LE_PORTSEL_MASK 3 - -/* control and status register 80 (csr80) */ -#define LE_C80_RCVFW(x) ((x) << 12) /* Receive FIFO Watermark */ -#define LE_C80_RCVFW_MAX 3 -#define LE_C80_XMTSP(x) ((x) << 10) /* Transmit Start Point */ -#define LE_C80_XMTSP_MAX 3 -#define LE_C80_XMTFW(x) ((x) << 8) /* Transmit FIFO Watermark */ -#define LE_C80_XMTFW_MAX 3 -#define LE_C80_DMATC 0x00ff /* DMA transfer counter */ - -/* control and status register 116 (csr116) */ -#define LE_C116_PME_EN_OVR 0x0400 /* PME_EN overwrite */ -#define LE_C116_LCDET 0x0200 /* link change detected */ -#define LE_C116_LCMODE 0x0100 /* link change wakeup mode */ -#define LE_C116_PMAT 0x0080 /* pattern matched */ -#define LE_C116_EMPPLBA 0x0040 /* magic packet physical logical - broadcast accept */ -#define LE_C116_MPMAT 0x0020 /* magic packet match */ -#define LE_C116_MPPEN 0x0010 /* magic packet pin enable */ -#define LE_C116_RST_POL 0x0001 /* PHY_RST pin polarity */ - -/* control and status register 122 (csr122) */ -#define LE_C122_RCVALGN 0x0001 /* receive packet align */ - -/* control and status register 124 (csr124) */ -#define LE_C124_RPA 0x0008 /* runt packet accept */ - -/* control and status register 125 (csr125) */ -#define LE_C125_IPG 0xff00 /* inter-packet gap */ -#define LE_C125_IFS1 0x00ff /* inter-frame spacing part 1 */ - -/* bus configuration register 0 (bcr0) */ -#define LE_B0_MSRDA 0xffff /* reserved locations */ - -/* bus configuration register 1 (bcr1) */ -#define LE_B1_MSWRA 0xffff /* reserved locations */ - -/* bus configuration register 2 (bcr2) */ -#define LE_B2_PHYSSELEN 0x2000 /* enable writes to BCR18[4:3] */ -#define LE_B2_LEDPE 0x1000 /* LED program enable */ -#define LE_B2_APROMWE 0x0100 /* Address PROM Write Enable */ -#define LE_B2_INTLEVEL 0x0080 /* 1 == edge triggered */ -#define LE_B2_DXCVRCTL 0x0020 /* DXCVR control */ -#define LE_B2_DXCVRPOL 0x0010 /* DXCVR polarity */ -#define LE_B2_EADISEL 0x0008 /* EADI select */ -#define LE_B2_AWAKE 0x0004 /* power saving mode select */ -#define LE_B2_ASEL 0x0002 /* auto-select PORTSEL */ -#define LE_B2_XMAUSEL 0x0001 /* reserved location */ - -/* bus configuration register 4 (bcr4) */ -/* bus configuration register 5 (bcr5) */ -/* bus configuration register 6 (bcr6) */ -/* bus configuration register 7 (bcr7) */ -/* bus configuration register 48 (bcr48) */ -#define LE_B4_LEDOUT 0x8000 /* LED output active */ -#define LE_B4_LEDPOL 0x4000 /* LED polarity */ -#define LE_B4_LEDDIS 0x2000 /* LED disable */ -#define LE_B4_100E 0x1000 /* 100Mb/s enable */ -#define LE_B4_MPSE 0x0200 /* magic packet status enable */ -#define LE_B4_FDLSE 0x0100 /* full-duplex link status enable */ -#define LE_B4_PSE 0x0080 /* pulse stretcher enable */ -#define LE_B4_LNKSE 0x0040 /* link status enable */ -#define LE_B4_RCVME 0x0020 /* receive match status enable */ -#define LE_B4_XMTE 0x0010 /* transmit status enable */ -#define LE_B4_POWER 0x0008 /* power enable */ -#define LE_B4_RCVE 0x0004 /* receive status enable */ -#define LE_B4_SPEED 0x0002 /* high speed enable */ -#define LE_B4_COLE 0x0001 /* collision status enable */ - -/* bus configuration register 9 (bcr9) */ -#define LE_B9_FDRPAD 0x0004 /* full-duplex runt packet accept - disable */ -#define LE_B9_AUIFD 0x0002 /* AUI full-duplex */ -#define LE_B9_FDEN 0x0001 /* full-duplex enable */ - -/* bus configuration register 18 (bcr18) */ -#define LE_B18_ROMTMG 0xf000 /* expansion rom timing */ -#define LE_B18_NOUFLO 0x0800 /* no underflow on transmit */ -#define LE_B18_MEMCMD 0x0200 /* memory read multiple enable */ -#define LE_B18_EXTREQ 0x0100 /* extended request */ -#define LE_B18_DWIO 0x0080 /* double-word I/O */ -#define LE_B18_BREADE 0x0040 /* burst read enable */ -#define LE_B18_BWRITE 0x0020 /* burst write enable */ -#define LE_B18_PHYSEL1 0x0010 /* PHYSEL 1 */ -#define LE_B18_PHYSEL0 0x0008 /* PHYSEL 0 */ - /* 00 ex ROM/Flash */ - /* 01 EADI/MII snoop */ - /* 10 reserved */ - /* 11 reserved */ -#define LE_B18_LINBC 0x0007 /* reserved locations */ - -/* bus configuration register 19 (bcr19) */ -#define LE_B19_PVALID 0x8000 /* EEPROM status valid */ -#define LE_B19_PREAD 0x4000 /* EEPROM read command */ -#define LE_B19_EEDET 0x2000 /* EEPROM detect */ -#define LE_B19_EEN 0x0010 /* EEPROM port enable */ -#define LE_B19_ECS 0x0004 /* EEPROM chip select */ -#define LE_B19_ESK 0x0002 /* EEPROM serial clock */ -#define LE_B19_EDI 0x0001 /* EEPROM data in */ -#define LE_B19_EDO 0x0001 /* EEPROM data out */ - -/* bus configuration register 20 (bcr20) */ -#define LE_B20_APERREN 0x0400 /* Advanced parity error handling */ -#define LE_B20_CSRPCNET 0x0200 /* PCnet-style CSRs (0 = ILACC) */ -#define LE_B20_SSIZE32 0x0100 /* Software Size 32-bit */ -#define LE_B20_SSTYLE 0x0007 /* Software Style */ -#define LE_B20_SSTYLE_LANCE 0 /* LANCE/PCnet-ISA (16-bit) */ -#define LE_B20_SSTYLE_ILACC 1 /* ILACC (32-bit) */ -#define LE_B20_SSTYLE_PCNETPCI2 2 /* PCnet-PCI (32-bit) */ -#define LE_B20_SSTYLE_PCNETPCI3 3 /* PCnet-PCI II (32-bit) */ - -/* bus configuration register 25 (bcr25) */ -#define LE_B25_SRAM_SIZE 0x00ff /* SRAM size */ - -/* bus configuration register 26 (bcr26) */ -#define LE_B26_SRAM_BND 0x00ff /* SRAM boundary */ - -/* bus configuration register 27 (bcr27) */ -#define LE_B27_PTRTST 0x8000 /* reserved for manuf. tests */ -#define LE_B27_LOLATRX 0x4000 /* low latency receive */ -#define LE_B27_EBCS 0x0038 /* expansion bus clock source */ - /* 000 CLK pin */ - /* 001 time base clock */ - /* 010 EBCLK pin */ - /* 011 reserved */ - /* 1xx reserved */ -#define LE_B27_CLK_FAC 0x0007 /* clock factor */ - /* 000 1 */ - /* 001 1/2 */ - /* 010 reserved */ - /* 011 1/4 */ - /* 1xx reserved */ - -/* bus configuration register 28 (bcr28) */ -#define LE_B28_EADDRL 0xffff /* expansion port address lower */ - -/* bus configuration register 29 (bcr29) */ -#define LE_B29_FLASH 0x8000 /* flash access */ -#define LE_B29_LAAINC 0x4000 /* lower address auto increment */ -#define LE_B29_EPADDRU 0x0007 /* expansion port address upper */ - -/* bus configuration register 30 (bcr30) */ -#define LE_B30_EBDATA 0xffff /* expansion bus data port */ - -/* bus configuration register 31 (bcr31) */ -#define LE_B31_STVAL 0xffff /* software timer value */ - -/* bus configuration register 32 (bcr32) */ -#define LE_B32_ANTST 0x8000 /* reserved for manuf. tests */ -#define LE_B32_MIIPD 0x4000 /* MII PHY Detect (manuf. tests) */ -#define LE_B32_FMDC 0x3000 /* fast management data clock */ -#define LE_B32_APEP 0x0800 /* auto-poll PHY */ -#define LE_B32_APDW 0x0700 /* auto-poll dwell time */ -#define LE_B32_DANAS 0x0080 /* disable autonegotiation */ -#define LE_B32_XPHYRST 0x0040 /* PHY reset */ -#define LE_B32_XPHYANE 0x0020 /* PHY autonegotiation enable */ -#define LE_B32_XPHYFD 0x0010 /* PHY full-duplex */ -#define LE_B32_XPHYSP 0x0008 /* PHY speed */ -#define LE_B32_MIIILP 0x0002 /* MII internal loopback */ - -/* bus configuration register 33 (bcr33) */ -#define LE_B33_SHADOW 0x8000 /* shadow enable */ -#define LE_B33_MII_SEL 0x4000 /* MII selected */ -#define LE_B33_ACOMP 0x2000 /* internal PHY autonegotiation comp */ -#define LE_B33_LINK 0x1000 /* link status */ -#define LE_B33_FDX 0x0800 /* full-duplex */ -#define LE_B33_SPEED 0x0400 /* 1 == high speed */ -#define LE_B33_PHYAD 0x03e0 /* PHY address */ -#define PHYAD_SHIFT 5 -#define LE_B33_REGAD 0x001f /* register address */ - -/* bus configuration register 34 (bcr34) */ -#define LE_B34_MIIMD 0xffff /* MII data */ - -/* bus configuration register 49 (bcr49) */ -#define LE_B49_PCNET 0x8000 /* PCnet mode - Must Be One */ -#define LE_B49_PHYSEL_D 0x0300 /* PHY_SEL_Default */ -#define LE_B49_PHYSEL_L 0x0010 /* PHY_SEL_Lock */ -#define LE_B49_PHYSEL 0x0003 /* PHYSEL */ - /* 00 10baseT PHY */ - /* 01 HomePNA PHY */ - /* 10 external PHY */ - /* 11 reserved */ - -/* Initialization block (mode) */ -#define LE_MODE_PROM 0x8000 /* promiscuous mode */ -/* 0x7f80 reserved, must be zero */ -/* 0x4000 - 0x0080 are not available on LANCE 7990. */ -#define LE_MODE_DRCVBC 0x4000 /* disable receive broadcast */ -#define LE_MODE_DRCVPA 0x2000 /* disable physical address detection */ -#define LE_MODE_DLNKTST 0x1000 /* disable link status */ -#define LE_MODE_DAPC 0x0800 /* disable automatic polarity correction */ -#define LE_MODE_MENDECL 0x0400 /* MENDEC loopback mode */ -#define LE_MODE_LRTTSEL 0x0200 /* lower receive threshold / - transmit mode selection */ -#define LE_MODE_PSEL1 0x0100 /* port selection bit1 */ -#define LE_MODE_PSEL0 0x0080 /* port selection bit0 */ -#define LE_MODE_INTL 0x0040 /* internal loopback */ -#define LE_MODE_DRTY 0x0020 /* disable retry */ -#define LE_MODE_COLL 0x0010 /* force a collision */ -#define LE_MODE_DTCR 0x0008 /* disable transmit CRC */ -#define LE_MODE_LOOP 0x0004 /* loopback mode */ -#define LE_MODE_DTX 0x0002 /* disable transmitter */ -#define LE_MODE_DRX 0x0001 /* disable receiver */ -#define LE_MODE_NORMAL 0 /* none of the above */ - -/* - * Chip ID (CSR88 IDL, CSR89 IDU) values for various AMD PCnet parts - */ -#define CHIPID_MANFID(x) (((x) >> 1) & 0x3ff) -#define CHIPID_PARTID(x) (((x) >> 12) & 0xffff) -#define CHIPID_VER(x) (((x) >> 28) & 0x7) - -#define PARTID_Am79c960 0x0003 -#define PARTID_Am79c961 0x2260 -#define PARTID_Am79c961A 0x2261 -#define PARTID_Am79c965 0x2430 /* yes, these... */ -#define PARTID_Am79c970 0x2430 /* ...are the same */ -#define PARTID_Am79c970A 0x2621 -#define PARTID_Am79c971 0x2623 -#define PARTID_Am79c972 0x2624 -#define PARTID_Am79c973 0x2625 -#define PARTID_Am79c978 0x2626 -#define PARTID_Am79c975 0x2627 -#define PARTID_Am79c976 0x2628 - -#endif /* !_DEV_LE_LANCEREG_H_ */ diff --git a/sys/dev/le/lancevar.h b/sys/dev/le/lancevar.h deleted file mode 100644 index 6232f5a776b0..000000000000 --- a/sys/dev/le/lancevar.h +++ /dev/null @@ -1,208 +0,0 @@ -/* $NetBSD: lancevar.h,v 1.10 2005/12/11 12:21:27 christos Exp $ */ - -/*- - * SPDX-License-Identifier: BSD-2-Clause - * - * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace - * Simulation Facility, NASA Ames Research Center. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - - -#ifndef _DEV_LE_LANCEVAR_H_ -#define _DEV_LE_LANCEVAR_H_ - -struct lance_softc { - if_t sc_ifp; - struct ifmedia sc_media; - struct mtx sc_mtx; - struct callout sc_wdog_ch; - int sc_wdog_timer; - - /* - * Memory functions: - * - * copy to/from descriptor - * copy to/from buffer - * zero bytes in buffer - */ - void (*sc_copytodesc)(struct lance_softc *, void *, int, int); - void (*sc_copyfromdesc)(struct lance_softc *, void *, int, int); - void (*sc_copytobuf)(struct lance_softc *, void *, int, int); - void (*sc_copyfrombuf)(struct lance_softc *, void *, int, int); - void (*sc_zerobuf)(struct lance_softc *, int, int); - - /* - * Machine-dependent functions: - * - * read/write CSR - * hardware reset hook - may be NULL - * hardware init hook - may be NULL - * no carrier hook - may be NULL - * media change hook - may be NULL - */ - uint16_t (*sc_rdcsr)(struct lance_softc *, uint16_t); - void (*sc_wrcsr)(struct lance_softc *, uint16_t, uint16_t); - void (*sc_hwreset)(struct lance_softc *); - void (*sc_hwinit)(struct lance_softc *); - int (*sc_hwintr)(struct lance_softc *); - void (*sc_nocarrier)(struct lance_softc *); - int (*sc_mediachange)(struct lance_softc *); - void (*sc_mediastatus)(struct lance_softc *, struct ifmediareq *); - - /* - * Media-supported by this interface. If this is NULL, - * the only supported media is assumed to be "manual". - */ - const int *sc_supmedia; - int sc_nsupmedia; - int sc_defaultmedia; - - uint16_t sc_conf3; /* CSR3 value */ - - void *sc_mem; /* base address of RAM - CPU's view */ - bus_addr_t sc_addr; /* base address of RAM - LANCE's view */ - - bus_size_t sc_memsize; /* size of RAM */ - - int sc_nrbuf; /* number of receive buffers */ - int sc_ntbuf; /* number of transmit buffers */ - int sc_last_rd; - int sc_first_td; - int sc_last_td; - int sc_no_td; - - int sc_initaddr; - int sc_rmdaddr; - int sc_tmdaddr; - int sc_rbufaddr; - int sc_tbufaddr; - - uint8_t sc_enaddr[ETHER_ADDR_LEN]; - - void (*sc_meminit)(struct lance_softc *); - void (*sc_start_locked)(struct lance_softc *); - - int sc_flags; -#define LE_ALLMULTI (1 << 0) -#define LE_BSWAP (1 << 1) -#define LE_CARRIER (1 << 2) -#define LE_DEBUG (1 << 3) -#define LE_PROMISC (1 << 4) -}; - -#define LE_LOCK_INIT(_sc, _name) \ - mtx_init(&(_sc)->sc_mtx, _name, MTX_NETWORK_LOCK, MTX_DEF) -#define LE_LOCK_INITIALIZED(_sc) mtx_initialized(&(_sc)->sc_mtx) -#define LE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) -#define LE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) -#define LE_LOCK_ASSERT(_sc, _what) mtx_assert(&(_sc)->sc_mtx, (_what)) -#define LE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx) - -/* - * Unfortunately, manual byte swapping is only necessary for the PCnet-PCI - * variants but not for the original LANCE or ILACC so we cannot do this - * with #ifdefs resolved at compile time. - */ -#define LE_HTOLE16(v) (((sc)->sc_flags & LE_BSWAP) ? htole16(v) : (v)) -#define LE_HTOLE32(v) (((sc)->sc_flags & LE_BSWAP) ? htole32(v) : (v)) -#define LE_LE16TOH(v) (((sc)->sc_flags & LE_BSWAP) ? le16toh(v) : (v)) -#define LE_LE32TOH(v) (((sc)->sc_flags & LE_BSWAP) ? le32toh(v) : (v)) - -int lance_config(struct lance_softc *, const char*, int); -void lance_attach(struct lance_softc *); -void lance_detach(struct lance_softc *); -void lance_suspend(struct lance_softc *); -void lance_resume(struct lance_softc *); -void lance_init_locked(struct lance_softc *); -int lance_put(struct lance_softc *, int, struct mbuf *); -struct mbuf *lance_get(struct lance_softc *, int, int); -void lance_setladrf(struct lance_softc *, u_int16_t *); - -/* - * The following functions are only useful on certain CPU/bus - * combinations. They should be written in assembly language for - * maximum efficiency, but machine-independent versions are provided - * for drivers that have not yet been optimized. - */ -void lance_copytobuf_contig(struct lance_softc *, void *, int, int); -void lance_copyfrombuf_contig(struct lance_softc *, void *, int, int); -void lance_zerobuf_contig(struct lance_softc *, int, int); - -#if 0 /* Example only - see lance.c */ -void lance_copytobuf_gap2(struct lance_softc *, void *, int, int); -void lance_copyfrombuf_gap2(struct lance_softc *, void *, int, int); -void lance_zerobuf_gap2(struct lance_softc *, int, int); - -void lance_copytobuf_gap16(struct lance_softc *, void *, int, int); -void lance_copyfrombuf_gap16(struct lance_softc *, void *, int, int); -void lance_zerobuf_gap16(struct lance_softc *, int, int); -#endif /* Example only */ - -/* - * Compare two Ether/802 addresses for equality, inlined and - * unrolled for speed. Use this like memcmp(). - * - * XXX: Add <machine/inlines.h> for stuff like this? - * XXX: or maybe add it to libkern.h instead? - * - * "I'd love to have an inline assembler version of this." - * XXX: Who wanted that? mycroft? I wrote one, but this - * version in C is as good as hand-coded assembly. -gwr - * - * Please do NOT tweak this without looking at the actual - * assembly code generated before and after your tweaks! - */ -static inline uint16_t -ether_cmp(void *one, void *two) -{ - uint16_t *a = (u_short *)one; - uint16_t *b = (u_short *)two; - uint16_t diff; - -#ifdef m68k - /* - * The post-increment-pointer form produces the best - * machine code for m68k. This was carefully tuned - * so it compiles to just 8 short (2-byte) op-codes! - */ - diff = *a++ - *b++; - diff |= *a++ - *b++; - diff |= *a++ - *b++; -#else - /* - * Most modern CPUs do better with a single expression. - * Note that short-cut evaluation is NOT helpful here, - * because it just makes the code longer, not faster! - */ - diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]); -#endif - - return (diff); -} - -#endif /* _DEV_LE_LANCEVAR_H_ */ diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c index 9d246d7c78fd..5fec3181aaff 100644 --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -286,7 +286,7 @@ struct md_s { struct { struct vnode *vnode; char file[PATH_MAX]; - vm_offset_t kva; + char *kva; } s_vnode; /* MD_SWAP related fields */ @@ -983,8 +983,7 @@ unmapped_step: ("npages %d too large", npages)); pmap_qenter(sc->s_vnode.kva, &bp->bio_ma[atop(ma_offs)], npages); - aiov.iov_base = (void *)(sc->s_vnode.kva + (ma_offs & - PAGE_MASK)); + aiov.iov_base = sc->s_vnode.kva + (ma_offs & PAGE_MASK); aiov.iov_len = iolen; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; @@ -1567,7 +1566,7 @@ mddestroy(struct md_s *sc, struct thread *td) sc->flags & MD_READONLY ? FREAD : (FREAD|FWRITE), sc->cred, td); } - if (sc->s_vnode.kva != 0) + if (sc->s_vnode.kva != NULL) kva_free(sc->s_vnode.kva, maxphys + PAGE_SIZE); break; case MD_SWAP: @@ -1617,7 +1616,6 @@ mdresize(struct md_s *sc, struct md_req *mdr) 0, 0); swap_release_by_cred(IDX_TO_OFF(oldpages - newpages), sc->cred); - sc->s_swap.object->charge = IDX_TO_OFF(newpages); sc->s_swap.object->size = newpages; VM_OBJECT_WUNLOCK(sc->s_swap.object); } else if (newpages > oldpages) { @@ -1637,7 +1635,6 @@ mdresize(struct md_s *sc, struct md_req *mdr) } } VM_OBJECT_WLOCK(sc->s_swap.object); - sc->s_swap.object->charge = IDX_TO_OFF(newpages); sc->s_swap.object->size = newpages; VM_OBJECT_WUNLOCK(sc->s_swap.object); } @@ -2134,7 +2131,7 @@ g_md_init(struct g_class *mp __unused) (long *) &paddr) != 0 || resource_int_value("md", i, "len", &len) != 0) break; - ptr = (char *)pmap_map(NULL, paddr, paddr + len, VM_PROT_READ); + ptr = pmap_map(NULL, paddr, paddr + len, VM_PROT_READ); if (ptr != NULL && len != 0) { sprintf(scratch, "preload%d 0x%016jx", i, (uintmax_t)paddr); diff --git a/sys/dev/mfi/mfi.c b/sys/dev/mfi/mfi.c index a7d98f06aea3..6f94e4203f1a 100644 --- a/sys/dev/mfi/mfi.c +++ b/sys/dev/mfi/mfi.c @@ -52,11 +52,10 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> #include "opt_mfi.h" -#include <sys/param.h> #include <sys/systm.h> +#include <sys/abi_compat.h> #include <sys/sysctl.h> #include <sys/malloc.h> #include <sys/kernel.h> @@ -372,7 +371,7 @@ mfi_attach(struct mfi_softc *sc) if (sc == NULL) return EINVAL; - device_printf(sc->mfi_dev, "Megaraid SAS driver Ver %s \n", + device_printf(sc->mfi_dev, "LSI MegaRAID SAS driver version: %s\n", MEGASAS_VERSION); mtx_init(&sc->mfi_io_lock, "MFI I/O lock", NULL, MTX_DEF); @@ -3084,8 +3083,6 @@ out: return (error); } -#define PTRIN(p) ((void *)(uintptr_t)(p)) - static int mfi_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td) { diff --git a/sys/dev/mfi/mfi_disk.c b/sys/dev/mfi/mfi_disk.c index 29c7bdc79aa1..999dcdfd1c97 100644 --- a/sys/dev/mfi/mfi_disk.c +++ b/sys/dev/mfi/mfi_disk.c @@ -70,7 +70,7 @@ static device_method_t mfi_disk_methods[] = { DEVMETHOD(device_probe, mfi_disk_probe), DEVMETHOD(device_attach, mfi_disk_attach), DEVMETHOD(device_detach, mfi_disk_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t mfi_disk_driver = { diff --git a/sys/dev/mfi/mfi_syspd.c b/sys/dev/mfi/mfi_syspd.c index 4353e2598f5c..979c3ea38d5b 100644 --- a/sys/dev/mfi/mfi_syspd.c +++ b/sys/dev/mfi/mfi_syspd.c @@ -75,7 +75,7 @@ static device_method_t mfi_syspd_methods[] = { DEVMETHOD(device_probe, mfi_syspd_probe), DEVMETHOD(device_attach, mfi_syspd_attach), DEVMETHOD(device_detach, mfi_syspd_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t mfi_syspd_driver = { diff --git a/sys/dev/mge/if_mge.c b/sys/dev/mge/if_mge.c index 25d213ff16ee..7ed40d898676 100644 --- a/sys/dev/mge/if_mge.c +++ b/sys/dev/mge/if_mge.c @@ -166,7 +166,7 @@ static device_method_t mge_methods[] = { /* MDIO interface */ DEVMETHOD(mdio_readreg, mge_mdio_readreg), DEVMETHOD(mdio_writereg, mge_mdio_writereg), - { 0, 0 } + DEVMETHOD_END }; DEFINE_CLASS_0(mge, mge_driver, mge_methods, sizeof(struct mge_softc)); diff --git a/sys/dev/mii/miivar.h b/sys/dev/mii/miivar.h index 5b0782775359..ef82d9f66a5d 100644 --- a/sys/dev/mii/miivar.h +++ b/sys/dev/mii/miivar.h @@ -250,7 +250,7 @@ struct mii_phydesc { (*(p)->mii_funcs->pf_reset)(p) enum miibus_device_ivars { - MIIBUS_IVAR_FLAGS + MIIBUS_IVAR_FLAGS = BUS_IVARS_PRIVATE }; /* diff --git a/sys/dev/mlx/mlx_disk.c b/sys/dev/mlx/mlx_disk.c index 3f00dfd92f9c..65567606f1b6 100644 --- a/sys/dev/mlx/mlx_disk.c +++ b/sys/dev/mlx/mlx_disk.c @@ -62,7 +62,7 @@ static device_method_t mlxd_methods[] = { DEVMETHOD(device_probe, mlxd_probe), DEVMETHOD(device_attach, mlxd_attach), DEVMETHOD(device_detach, mlxd_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t mlxd_driver = { diff --git a/sys/dev/mlx4/mlx4_core/mlx4_main.c b/sys/dev/mlx4/mlx4_core/mlx4_main.c index ca63d1d12ba6..302b9d9cc2f4 100644 --- a/sys/dev/mlx4/mlx4_core/mlx4_main.c +++ b/sys/dev/mlx4/mlx4_core/mlx4_main.c @@ -135,7 +135,7 @@ static struct mlx4_profile default_profile = { .num_cq = 1 << 16, .num_mcg = 1 << 13, .num_mpt = 1 << 19, - .num_mtt = 1 << 20, /* It is really num mtt segements */ + .num_mtt = 1 << 20, /* It is really num mtt segments */ }; static struct mlx4_profile low_mem_profile = { diff --git a/sys/dev/mlx5/driver.h b/sys/dev/mlx5/driver.h index cdefe7e013f6..ba6714c5c7b6 100644 --- a/sys/dev/mlx5/driver.h +++ b/sys/dev/mlx5/driver.h @@ -890,6 +890,7 @@ struct mlx5_cmd_work_ent { u16 op; u8 busy; bool polling; + struct work_struct freew; }; struct mlx5_pas { diff --git a/sys/dev/mlx5/mlx5_accel/ipsec.h b/sys/dev/mlx5/mlx5_accel/ipsec.h index c3f3a2372482..8685c07e84db 100644 --- a/sys/dev/mlx5/mlx5_accel/ipsec.h +++ b/sys/dev/mlx5/mlx5_accel/ipsec.h @@ -204,6 +204,7 @@ struct mlx5e_ipsec_pol_entry { /* This function doesn't really belong here, but let's put it here for now */ void mlx5_object_change_event(struct mlx5_core_dev *dev, struct mlx5_eqe *eqe); +void mlx5e_ipsec_report(struct mlx5e_priv *priv); int mlx5e_ipsec_init(struct mlx5e_priv *priv); void mlx5e_ipsec_cleanup(struct mlx5e_priv *priv); diff --git a/sys/dev/mlx5/mlx5_accel/mlx5_ipsec.c b/sys/dev/mlx5/mlx5_accel/mlx5_ipsec.c index 3f3c575c9dad..325c70969306 100644 --- a/sys/dev/mlx5/mlx5_accel/mlx5_ipsec.c +++ b/sys/dev/mlx5/mlx5_accel/mlx5_ipsec.c @@ -418,24 +418,30 @@ err_xfrm: return err; } -#define GET_TRUNK_IF(vifp, ifp, ept) \ - if (if_gettype(vifp) == IFT_L2VLAN) { \ - NET_EPOCH_ENTER(ept); \ - ifp = VLAN_TRUNKDEV(vifp); \ - NET_EPOCH_EXIT(ept); \ - } else { \ - ifp = vifp; \ +static struct ifnet * +mlx5_get_trunk_if(struct ifnet *vifp) +{ + struct epoch_tracker et; + struct ifnet *res; + + if (if_gettype(vifp) == IFT_L2VLAN) { + NET_EPOCH_ENTER(et); + res = VLAN_TRUNKDEV(vifp); + NET_EPOCH_EXIT(et); + } else { + res = vifp; } + return (res); +} static int mlx5e_if_sa_newkey(struct ifnet *ifpo, void *sav, u_int dev_spi, void **privp) { struct mlx5e_ipsec_priv_bothdir *pb; - struct epoch_tracker et; struct ifnet *ifp; int error; - GET_TRUNK_IF(ifpo, ifp, et); + ifp = mlx5_get_trunk_if(ifpo); pb = malloc(sizeof(struct mlx5e_ipsec_priv_bothdir), M_DEVBUF, M_WAITOK | M_ZERO); @@ -478,10 +484,9 @@ static int mlx5e_if_sa_deinstall(struct ifnet *ifpo, u_int dev_spi, void *priv) { struct mlx5e_ipsec_priv_bothdir pb, *pbp; - struct epoch_tracker et; struct ifnet *ifp; - GET_TRUNK_IF(ifpo, ifp, et); + ifp = mlx5_get_trunk_if(ifpo); pbp = priv; pb = *(struct mlx5e_ipsec_priv_bothdir *)priv; @@ -516,10 +521,9 @@ mlx5e_if_sa_cnt(struct ifnet *ifpo, void *sa, uint32_t drv_spi, void *priv, struct mlx5e_ipsec_priv_bothdir *pb; u64 packets_in, packets_out; u64 bytes_in, bytes_out; - struct epoch_tracker et; struct ifnet *ifp; - GET_TRUNK_IF(ifpo, ifp, et); + ifp = mlx5_get_trunk_if(ifpo); pb = priv; mlx5e_if_sa_cnt_one(ifp, sa, drv_spi, pb->priv_in, @@ -652,12 +656,11 @@ mlx5e_if_spd_install(struct ifnet *ifpo, void *sp, void *inp1, void **ifdatap) { struct mlx5e_ipsec_pol_entry *pol_entry; struct mlx5e_priv *priv; - struct epoch_tracker et; u16 vid = VLAN_NONE; struct ifnet *ifp; int err; - GET_TRUNK_IF(ifpo, ifp, et); + ifp = mlx5_get_trunk_if(ifpo); if (if_gettype(ifpo) == IFT_L2VLAN) VLAN_TAG(ifpo, &vid); priv = if_getsoftc(ifp); @@ -739,13 +742,14 @@ static const struct if_ipsec_accel_methods mlx5e_ipsec_funcs = { .if_hwassist = mlx5e_if_ipsec_hwassist, }; -int mlx5e_ipsec_init(struct mlx5e_priv *priv) +void +mlx5e_ipsec_report(struct mlx5e_priv *priv) { - struct mlx5_core_dev *mdev = priv->mdev; - struct mlx5e_ipsec *pipsec; - if_t ifp = priv->ifp; - int ret; + struct mlx5_core_dev *mdev; + if (!bootverbose) + return; + mdev = priv->mdev; mlx5_core_info(mdev, "ipsec " "offload %d log_max_dek %d gen_obj_types %d " "ipsec_encrypt %d ipsec_decrypt %d " @@ -775,6 +779,14 @@ int mlx5e_ipsec_init(struct mlx5e_priv *priv) MLX5_CAP_FLOWTABLE_NIC_RX(mdev, reformat_del_esp_transport_over_udp) != 0, MLX5_CAP_IPSEC(mdev, ipsec_esn) != 0); +} + +int mlx5e_ipsec_init(struct mlx5e_priv *priv) +{ + struct mlx5_core_dev *mdev = priv->mdev; + struct mlx5e_ipsec *pipsec; + if_t ifp = priv->ifp; + int ret; if (!(mlx5_ipsec_device_caps(mdev) & MLX5_IPSEC_CAP_PACKET_OFFLOAD)) { mlx5_core_dbg(mdev, "Not an IPSec offload device\n"); diff --git a/sys/dev/mlx5/mlx5_core/mlx5_cmd.c b/sys/dev/mlx5/mlx5_core/mlx5_cmd.c index 86c721a83cb7..e314a04c294f 100644 --- a/sys/dev/mlx5/mlx5_core/mlx5_cmd.c +++ b/sys/dev/mlx5/mlx5_core/mlx5_cmd.c @@ -802,6 +802,15 @@ static void cb_timeout_handler(struct work_struct *work) mlx5_cmd_comp_handler(dev, 1UL << ent->idx, MLX5_CMD_MODE_EVENTS); } +static void +cmd_free_work(struct work_struct *work) +{ + struct mlx5_cmd_work_ent *ent = container_of(work, + struct mlx5_cmd_work_ent, freew); + + free_cmd(ent); +} + static void complete_command(struct mlx5_cmd_work_ent *ent) { struct mlx5_cmd *cmd = ent->cmd; @@ -856,7 +865,8 @@ static void complete_command(struct mlx5_cmd_work_ent *ent) free_msg(dev, ent->in); err = err ? err : ent->status; - free_cmd(ent); + INIT_WORK(&ent->freew, cmd_free_work); + schedule_work(&ent->freew); callback(err, context); } else { complete(&ent->done); diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c index daa98752c59b..9bcb0dcf8e16 100644 --- a/sys/dev/mlx5/mlx5_en/mlx5_en_main.c +++ b/sys/dev/mlx5/mlx5_en/mlx5_en_main.c @@ -1135,6 +1135,25 @@ mlx5e_hw_clock(struct mlx5e_priv *priv) } /* + * Seed the first calibration point so that base_prev and clbr_hw_prev + * are always valid. Called once during attach before the first + * calibration callout fires. + */ +static void +mlx5e_seed_calibration(struct mlx5e_priv *priv) +{ + struct mlx5e_clbr_point *cp; + struct timespec ts; + + cp = &priv->clbr_points[0]; + cp->clbr_hw_curr = mlx5e_hw_clock(priv); + nanouptime(&ts); + cp->base_curr = mlx5e_timespec2usec(&ts); + cp->clbr_hw_prev = cp->clbr_hw_curr - 1; + cp->base_prev = cp->base_curr - 1; +} + +/* * The calibration callout, it runs either in the context of the * thread which enables calibration, or in callout. It takes the * snapshot of system and adapter clocks, then advances the pointers to @@ -1147,6 +1166,9 @@ mlx5e_calibration_callout(void *arg) struct mlx5e_priv *priv; struct mlx5e_clbr_point *next, *curr; struct timespec ts; + uint64_t hw_delta_new, hw_delta_old; + uint64_t old_nsec, old_projected, old_sec; + uint64_t res_n, res_s, res_s_mod, rt_delta_old; int clbr_curr_next; priv = arg; @@ -1175,6 +1197,33 @@ mlx5e_calibration_callout(void *arg) nanouptime(&ts); next->base_curr = mlx5e_timespec2usec(&ts); + /* + * Ensure monotonicity across calibration transitions. Compute + * what the old calibration would extrapolate to at the new + * hw_curr. If the new base_curr is less, clamp it so the new + * slope is at least as steep as the old one. This prevents + * packets from seeing time go backwards when the slope drops. + * + * Use the same split-seconds technique as mlx5e_mbuf_tstmp() + * to avoid overflowing uint64_t in the multiplication. + */ + hw_delta_new = next->clbr_hw_curr - curr->clbr_hw_curr; + rt_delta_old = curr->base_curr - curr->base_prev; + hw_delta_old = curr->clbr_hw_curr - curr->clbr_hw_prev; + old_sec = hw_delta_new / priv->cclk; + old_nsec = hw_delta_new % priv->cclk; + res_s = old_sec * rt_delta_old; + res_n = old_nsec * rt_delta_old; + res_s_mod = res_s % hw_delta_old; + res_s /= hw_delta_old; + res_s_mod *= priv->cclk; + res_n += res_s_mod; + res_n /= hw_delta_old; + res_s *= priv->cclk; + old_projected = curr->base_curr + res_s + res_n; + if (next->base_curr < old_projected) + next->base_curr = old_projected; + curr->clbr_gen = 0; atomic_thread_fence_rel(); priv->clbr_curr = clbr_curr_next; @@ -3728,6 +3777,8 @@ out: break; case SIOCGI2C: + /* fallthru */ + case SIOCGI2CPB: ifr = (struct ifreq *)data; /* @@ -3737,6 +3788,9 @@ out: error = copyin(ifr_data_get_ptr(ifr), &i2c, sizeof(i2c)); if (error) break; + /* ensure page and bank are 0 for legacy SIOCGI2C ioctls */ + if (command == SIOCGI2C) + i2c.page = i2c.bank = 0; if (i2c.len > sizeof(i2c.data)) { error = EINVAL; @@ -3778,8 +3832,17 @@ out: error = EINVAL; goto err_i2c; } + + if (i2c.bank != 0) { + mlx5_en_err(ifp, + "Query eeprom failed, Invalid Bank: %X\n", + i2c.bank); + error = EINVAL; + goto err_i2c; + } + error = mlx5_query_eeprom(priv->mdev, - read_addr, MLX5_EEPROM_LOW_PAGE, + read_addr, i2c.page, (uint32_t)i2c.offset, (uint32_t)i2c.len, module_num, (uint32_t *)i2c.data, &size_read); if (error) { @@ -3791,7 +3854,7 @@ out: if (i2c.len > MLX5_EEPROM_MAX_BYTES) { error = mlx5_query_eeprom(priv->mdev, - read_addr, MLX5_EEPROM_LOW_PAGE, + read_addr, i2c.page, (uint32_t)(i2c.offset + size_read), (uint32_t)(i2c.len - size_read), module_num, (uint32_t *)(i2c.data + size_read), &size_read); @@ -4713,6 +4776,9 @@ mlx5e_create_ifp(struct mlx5_core_dev *mdev) goto err_rl_init; } +#ifdef IPSEC_OFFLOAD + mlx5e_ipsec_report(priv); +#endif if ((if_getcapenable2(ifp) & IFCAP2_BIT(IFCAP2_IPSEC_OFFLOAD)) != 0) { err = mlx5e_ipsec_init(priv); if (err) { @@ -4870,6 +4936,7 @@ mlx5e_create_ifp(struct mlx5_core_dev *mdev) callout_init(&priv->tstmp_clbr, 1); /* Pull out the frequency of the clock in hz */ priv->cclk = (uint64_t)MLX5_CAP_GEN(mdev, device_frequency_khz) * 1000ULL; + mlx5e_seed_calibration(priv); mlx5e_reset_calibration_callout(priv); pa.pa_version = PFIL_VERSION; diff --git a/sys/dev/mmc/mmcbrvar.h b/sys/dev/mmc/mmcbrvar.h index c47966793098..06d38553c201 100644 --- a/sys/dev/mmc/mmcbrvar.h +++ b/sys/dev/mmc/mmcbrvar.h @@ -60,7 +60,7 @@ #include "mmcbr_if.h" enum mmcbr_device_ivars { - MMCBR_IVAR_BUS_TYPE, + MMCBR_IVAR_BUS_TYPE = BUS_IVARS_PRIVATE, MMCBR_IVAR_BUS_MODE, MMCBR_IVAR_BUS_WIDTH, MMCBR_IVAR_CHIP_SELECT, diff --git a/sys/dev/mmc/mmcvar.h b/sys/dev/mmc/mmcvar.h index 268b298bce58..a335e098d2ad 100644 --- a/sys/dev/mmc/mmcvar.h +++ b/sys/dev/mmc/mmcvar.h @@ -56,7 +56,7 @@ #define DEV_MMC_MMCVAR_H enum mmc_device_ivars { - MMC_IVAR_SPEC_VERS, + MMC_IVAR_SPEC_VERS = BUS_IVARS_PRIVATE, MMC_IVAR_DSR_IMP, MMC_IVAR_MEDIA_SIZE, MMC_IVAR_RCA, diff --git a/sys/dev/mpi3mr/mpi3mr_pci.c b/sys/dev/mpi3mr/mpi3mr_pci.c index b436541b26c0..89b87c4e2ef7 100644 --- a/sys/dev/mpi3mr/mpi3mr_pci.c +++ b/sys/dev/mpi3mr/mpi3mr_pci.c @@ -65,7 +65,7 @@ static device_method_t mpi3mr_methods[] = { DEVMETHOD(device_resume, mpi3mr_pci_resume), DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_driver_added, bus_generic_driver_added), - { 0, 0 } + DEVMETHOD_END }; char fmt_os_ver[16]; diff --git a/sys/dev/mpr/mpr.c b/sys/dev/mpr/mpr.c index 262d6b58b705..9bceabe637b5 100644 --- a/sys/dev/mpr/mpr.c +++ b/sys/dev/mpr/mpr.c @@ -30,7 +30,6 @@ * */ -#include <sys/cdefs.h> /* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ diff --git a/sys/dev/mpr/mpr_config.c b/sys/dev/mpr/mpr_config.c index b7882feed158..8a36a12a225c 100644 --- a/sys/dev/mpr/mpr_config.c +++ b/sys/dev/mpr/mpr_config.c @@ -28,7 +28,6 @@ * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD */ -#include <sys/cdefs.h> /* TODO Move headers to mprvar */ #include <sys/types.h> #include <sys/param.h> diff --git a/sys/dev/mpr/mpr_mapping.c b/sys/dev/mpr/mpr_mapping.c index 38aa4dfc7ef2..a907ebafe2ff 100644 --- a/sys/dev/mpr/mpr_mapping.c +++ b/sys/dev/mpr/mpr_mapping.c @@ -28,7 +28,6 @@ * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD */ -#include <sys/cdefs.h> /* TODO Move headers to mprvar */ #include <sys/types.h> #include <sys/param.h> diff --git a/sys/dev/mpr/mpr_pci.c b/sys/dev/mpr/mpr_pci.c index 6b74f7e38811..27b90c31b521 100644 --- a/sys/dev/mpr/mpr_pci.c +++ b/sys/dev/mpr/mpr_pci.c @@ -24,7 +24,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> /* PCI/PCI-X/PCIe bus interface for the Avago Tech (LSI) MPT3 controllers */ /* TODO Move headers to mprvar */ @@ -77,7 +76,7 @@ static device_method_t mpr_methods[] = { DEVMETHOD(device_resume, mpr_pci_resume), DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_driver_added, bus_generic_driver_added), - { 0, 0 } + DEVMETHOD_END }; static driver_t mpr_pci_driver = { diff --git a/sys/dev/mpr/mpr_sas.c b/sys/dev/mpr/mpr_sas.c index 5f3a27a468b0..f0470de3efcf 100644 --- a/sys/dev/mpr/mpr_sas.c +++ b/sys/dev/mpr/mpr_sas.c @@ -30,7 +30,6 @@ * */ -#include <sys/cdefs.h> /* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ @@ -86,6 +85,12 @@ #define MPRSAS_DISCOVERY_TIMEOUT 20 #define MPRSAS_MAX_DISCOVERY_TIMEOUTS 10 /* 200 seconds */ +#include <sys/sdt.h> + +/* SDT Probes */ +SDT_PROBE_DEFINE4(cam, , mpr, complete, "union ccb *", + "struct mpr_command *", "u_int", "u32"); + /* * static array to check SCSI OpCode for EEDP protection bits */ @@ -2540,6 +2545,9 @@ mprsas_scsiio_complete(struct mpr_softc *sc, struct mpr_command *cm) sc->SSU_refcount--; } + SDT_PROBE4(cam, , mpr, complete, ccb, cm, sassc->flags, + sc->mapping_table[target_id].device_info); + /* Take the fast path to completion */ if (cm->cm_reply == NULL) { if (mprsas_get_ccbstatus(ccb) == CAM_REQ_INPROG) { diff --git a/sys/dev/mpr/mpr_sas_lsi.c b/sys/dev/mpr/mpr_sas_lsi.c index 9ba776e49e7a..f88dd6e2532f 100644 --- a/sys/dev/mpr/mpr_sas_lsi.c +++ b/sys/dev/mpr/mpr_sas_lsi.c @@ -28,7 +28,6 @@ * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD */ -#include <sys/cdefs.h> /* Communications core for Avago Technologies (LSI) MPT3 */ /* TODO Move headers to mprvar */ @@ -1517,7 +1516,6 @@ mprsas_SSU_to_SATA_devices(struct mpr_softc *sc, int howto) /*start*/FALSE, /*load/eject*/0, /*immediate*/FALSE, - /*power_condition*/SSS_PC_START_VALID, MPR_SENSE_LEN, /*timeout*/10000); xpt_action(ccb); diff --git a/sys/dev/mpr/mpr_table.c b/sys/dev/mpr/mpr_table.c index 910f47bb2937..b47b5259c63d 100644 --- a/sys/dev/mpr/mpr_table.c +++ b/sys/dev/mpr/mpr_table.c @@ -24,7 +24,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> /* Debugging tables for MPT2 */ /* TODO Move headers to mprvar */ diff --git a/sys/dev/mpr/mpr_user.c b/sys/dev/mpr/mpr_user.c index 5245129ce8c1..826528a3aeaf 100644 --- a/sys/dev/mpr/mpr_user.c +++ b/sys/dev/mpr/mpr_user.c @@ -59,7 +59,6 @@ * Broadcom Inc. (LSI) MPT-Fusion Host Adapter FreeBSD */ -#include <sys/cdefs.h> /* TODO Move headers to mprvar */ #include <sys/types.h> #include <sys/param.h> diff --git a/sys/dev/mps/mps.c b/sys/dev/mps/mps.c index 357eacf28925..cb82045356fc 100644 --- a/sys/dev/mps/mps.c +++ b/sys/dev/mps/mps.c @@ -30,7 +30,6 @@ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ -#include <sys/cdefs.h> /* Communications core for Avago Technologies (LSI) MPT2 */ /* TODO Move headers to mpsvar */ diff --git a/sys/dev/mps/mps_config.c b/sys/dev/mps/mps_config.c index 47f9fe573a2b..cfb96c3e9bee 100644 --- a/sys/dev/mps/mps_config.c +++ b/sys/dev/mps/mps_config.c @@ -29,7 +29,6 @@ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ -#include <sys/cdefs.h> /* TODO Move headers to mpsvar */ #include <sys/types.h> #include <sys/param.h> diff --git a/sys/dev/mps/mps_mapping.c b/sys/dev/mps/mps_mapping.c index 25d17d575970..9e069a3a924d 100644 --- a/sys/dev/mps/mps_mapping.c +++ b/sys/dev/mps/mps_mapping.c @@ -29,7 +29,6 @@ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ -#include <sys/cdefs.h> /* TODO Move headers to mpsvar */ #include <sys/types.h> #include <sys/param.h> diff --git a/sys/dev/mps/mps_pci.c b/sys/dev/mps/mps_pci.c index 7a0c577eb72a..8855c186754a 100644 --- a/sys/dev/mps/mps_pci.c +++ b/sys/dev/mps/mps_pci.c @@ -26,7 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> /* PCI/PCI-X/PCIe bus interface for the Avago Tech (LSI) MPT2 controllers */ /* TODO Move headers to mpsvar */ diff --git a/sys/dev/mps/mps_sas.c b/sys/dev/mps/mps_sas.c index fa0f817ed67b..fb591391f6a5 100644 --- a/sys/dev/mps/mps_sas.c +++ b/sys/dev/mps/mps_sas.c @@ -30,7 +30,6 @@ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ -#include <sys/cdefs.h> /* Communications core for Avago Technologies (LSI) MPT2 */ /* TODO Move headers to mpsvar */ @@ -81,6 +80,12 @@ #include <dev/mps/mps_table.h> #include <dev/mps/mps_sas.h> +#include <sys/sdt.h> + +/* SDT Probes */ +SDT_PROBE_DEFINE4(cam, , mps, complete, "union ccb *", + "struct mps_command *", "u_int", "u32"); + /* * static array to check SCSI OpCode for EEDP protection bits */ @@ -2077,6 +2082,9 @@ mpssas_scsiio_complete(struct mps_softc *sc, struct mps_command *cm) sc->SSU_refcount--; } + SDT_PROBE4(cam, , mps, complete, ccb, cm, sassc->flags, + sc->mapping_table[target_id].device_info); + /* Take the fast path to completion */ if (cm->cm_reply == NULL) { if (mpssas_get_ccbstatus(ccb) == CAM_REQ_INPROG) { diff --git a/sys/dev/mps/mps_sas_lsi.c b/sys/dev/mps/mps_sas_lsi.c index 42119b5c0a43..bcde5d69a021 100644 --- a/sys/dev/mps/mps_sas_lsi.c +++ b/sys/dev/mps/mps_sas_lsi.c @@ -29,7 +29,6 @@ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ -#include <sys/cdefs.h> /* Communications core for Avago Technologies (LSI) MPT2 */ /* TODO Move headers to mpsvar */ @@ -1153,7 +1152,6 @@ mpssas_SSU_to_SATA_devices(struct mps_softc *sc, int howto) /*start*/FALSE, /*load/eject*/0, /*immediate*/FALSE, - /*power_condition*/SSS_PC_START_VALID, MPS_SENSE_LEN, /*timeout*/10000); xpt_action(ccb); diff --git a/sys/dev/mps/mps_table.c b/sys/dev/mps/mps_table.c index f2c6ed9b88c3..e97583ffa3f8 100644 --- a/sys/dev/mps/mps_table.c +++ b/sys/dev/mps/mps_table.c @@ -26,7 +26,6 @@ * SUCH DAMAGE. */ -#include <sys/cdefs.h> /* Debugging tables for MPT2 */ /* TODO Move headers to mpsvar */ diff --git a/sys/dev/mps/mps_user.c b/sys/dev/mps/mps_user.c index 01edcbed2609..619eea6e9c69 100644 --- a/sys/dev/mps/mps_user.c +++ b/sys/dev/mps/mps_user.c @@ -60,7 +60,6 @@ * Avago Technologies (LSI) MPT-Fusion Host Adapter FreeBSD */ -#include <sys/cdefs.h> /* TODO Move headers to mpsvar */ #include <sys/types.h> #include <sys/param.h> diff --git a/sys/dev/mrsas/mrsas.c b/sys/dev/mrsas/mrsas.c index e362d4b455fc..379fcbcb19ca 100644 --- a/sys/dev/mrsas/mrsas.c +++ b/sys/dev/mrsas/mrsas.c @@ -349,15 +349,9 @@ mrsas_find_ident(device_t dev) static int mrsas_probe(device_t dev) { - static u_int8_t first_ctrl = 1; struct mrsas_ident *id; if ((id = mrsas_find_ident(dev)) != NULL) { - if (first_ctrl) { - printf("AVAGO MegaRAID SAS FreeBSD mrsas driver version: %s\n", - MRSAS_VERSION); - first_ctrl = 0; - } device_set_desc(dev, id->desc); /* between BUS_PROBE_DEFAULT and BUS_PROBE_LOW_PRIORITY */ return (-30); @@ -830,6 +824,9 @@ mrsas_attach(device_t dev) struct mrsas_softc *sc = device_get_softc(dev); uint32_t cmd, error; + device_printf(dev, "AVAGO MegaRAID SAS driver version: %s\n", + MRSAS_VERSION); + memset(sc, 0, sizeof(struct mrsas_softc)); /* Look up our softc and initialize its fields. */ diff --git a/sys/dev/mvs/mvs.c b/sys/dev/mvs/mvs.c index 4132af157a62..aafe68d04685 100644 --- a/sys/dev/mvs/mvs.c +++ b/sys/dev/mvs/mvs.c @@ -579,7 +579,7 @@ static device_method_t mvsch_methods[] = { DEVMETHOD(device_detach, mvs_ch_detach), DEVMETHOD(device_suspend, mvs_ch_suspend), DEVMETHOD(device_resume, mvs_ch_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t mvsch_driver = { "mvsch", diff --git a/sys/dev/mvs/mvs_pci.c b/sys/dev/mvs/mvs_pci.c index 322da77968cf..19bc52d91050 100644 --- a/sys/dev/mvs/mvs_pci.c +++ b/sys/dev/mvs/mvs_pci.c @@ -510,7 +510,7 @@ static device_method_t mvs_methods[] = { DEVMETHOD(bus_child_location, mvs_child_location), DEVMETHOD(bus_get_dma_tag, mvs_get_dma_tag), DEVMETHOD(mvs_edma, mvs_edma), - { 0, 0 } + DEVMETHOD_END }; static driver_t mvs_driver = { "mvs", diff --git a/sys/dev/mvs/mvs_soc.c b/sys/dev/mvs/mvs_soc.c index 8dc5ed7a3034..30e61f2e94fc 100644 --- a/sys/dev/mvs/mvs_soc.c +++ b/sys/dev/mvs/mvs_soc.c @@ -448,7 +448,7 @@ static device_method_t mvs_methods[] = { DEVMETHOD(bus_child_location, mvs_child_location), DEVMETHOD(bus_get_dma_tag, mvs_get_dma_tag), DEVMETHOD(mvs_edma, mvs_edma), - { 0, 0 } + DEVMETHOD_END }; static driver_t mvs_driver = { "mvs", diff --git a/sys/dev/mwl/if_mwl.c b/sys/dev/mwl/if_mwl.c index 9f3d34f4f50d..513c3d9c60e4 100644 --- a/sys/dev/mwl/if_mwl.c +++ b/sys/dev/mwl/if_mwl.c @@ -1638,28 +1638,43 @@ _mwl_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k, switch (cip->ic_cipher) { case IEEE80211_CIPHER_WEP: hk.keyTypeId = KEY_TYPE_ID_WEP; - hk.keyLen = k->wk_keylen; + hk.keyLen = ieee80211_crypto_get_key_len(k); if (k->wk_keyix == vap->iv_def_txkey) hk.keyFlags = KEY_FLAG_WEP_TXKEY; if (!IEEE80211_IS_STATICKEY(k)) { /* NB: WEP is never used for the PTK */ (void) addgroupflags(&hk, k); } + memcpy(hk.key.aes, ieee80211_crypto_get_key_data(k), + ieee80211_crypto_get_key_len(k)); break; case IEEE80211_CIPHER_TKIP: hk.keyTypeId = KEY_TYPE_ID_TKIP; hk.key.tkip.tsc.high = (uint32_t)(k->wk_keytsc >> 16); hk.key.tkip.tsc.low = (uint16_t)k->wk_keytsc; hk.keyFlags = KEY_FLAG_TSC_VALID | KEY_FLAG_MICKEY_VALID; - hk.keyLen = k->wk_keylen + IEEE80211_MICBUF_SIZE; + hk.keyLen = ieee80211_crypto_get_key_len(k) + + IEEE80211_MICBUF_SIZE; if (!addgroupflags(&hk, k)) hk.keyFlags |= KEY_FLAG_PAIRWISE; + + /* Copy in TKIP MIC after the 16 byte main key */ + memcpy(hk.key.aes, ieee80211_crypto_get_key_data(k), + ieee80211_crypto_get_key_len(k)); + memcpy(hk.key.aes + IEEE80211_KEYBUF_SIZE, + ieee80211_crypto_get_key_txmic_data(k), + 8); + memcpy(hk.key.aes + IEEE80211_KEYBUF_SIZE + 8, + ieee80211_crypto_get_key_rxmic_data(k), + 8); break; case IEEE80211_CIPHER_AES_CCM: hk.keyTypeId = KEY_TYPE_ID_AES; - hk.keyLen = k->wk_keylen; + hk.keyLen = ieee80211_crypto_get_key_len(k); if (!addgroupflags(&hk, k)) hk.keyFlags |= KEY_FLAG_PAIRWISE; + memcpy(hk.key.aes, ieee80211_crypto_get_key_data(k), + ieee80211_crypto_get_key_len(k)); break; default: /* XXX should not happen */ @@ -1667,11 +1682,6 @@ _mwl_key_set(struct ieee80211vap *vap, const struct ieee80211_key *k, __func__, k->wk_cipher->ic_cipher); return 0; } - /* - * NB: tkip mic keys get copied here too; the layout - * just happens to match that in ieee80211_key. - */ - memcpy(hk.key.aes, k->wk_key, hk.keyLen); /* * Locate address of sta db entry for writing key; diff --git a/sys/dev/mxge/if_mxge.c b/sys/dev/mxge/if_mxge.c index f36f41d53b40..04f535e5f7c9 100644 --- a/sys/dev/mxge/if_mxge.c +++ b/sys/dev/mxge/if_mxge.c @@ -183,7 +183,7 @@ mxge_enable_wc(mxge_softc_t *sc) sc->wc = 1; len = rman_get_size(sc->mem_res); - err = pmap_change_attr((vm_offset_t) sc->sram, + err = pmap_change_attr(__DEVOLATILE(void *, sc->sram), len, PAT_WRITE_COMBINING); if (err != 0) { device_printf(sc->dev, "pmap_change_attr failed, %d\n", @@ -1804,7 +1804,7 @@ mxge_encap_tso(struct mxge_slice_state *ss, struct mbuf *m, uint32_t low, high_swapped; int len, seglen, cum_len, cum_len_next; int next_is_first, chop, cnt, rdma_count, small; - uint16_t pseudo_hdr_offset, cksum_offset, mss, sum; + uint16_t pseudo_hdr_offset, cksum_offset, mss, sum = 0; uint8_t flags, flags_next; static int once; diff --git a/sys/dev/ncthwm/ncthwm.c b/sys/dev/ncthwm/ncthwm.c index b36f677703ea..99d32be8a82d 100644 --- a/sys/dev/ncthwm/ncthwm.c +++ b/sys/dev/ncthwm/ncthwm.c @@ -244,7 +244,7 @@ static device_method_t ncthwm_methods[] = { DEVMETHOD(device_detach, ncthwm_detach), /* Terminate method list */ - { 0, 0 } + DEVMETHOD_END }; static driver_t ncthwm_driver = { diff --git a/sys/dev/nfsmb/nfsmb.c b/sys/dev/nfsmb/nfsmb.c index b88b2ca0001f..9e59966481e5 100644 --- a/sys/dev/nfsmb/nfsmb.c +++ b/sys/dev/nfsmb/nfsmb.c @@ -601,7 +601,7 @@ static device_method_t nfsmb_methods[] = { DEVMETHOD(smbus_readw, nfsmb_readw), DEVMETHOD(smbus_bwrite, nfsmb_bwrite), DEVMETHOD(smbus_bread, nfsmb_bread), - { 0, 0 } + DEVMETHOD_END }; static device_method_t nfsmbsub_methods[] = { @@ -621,7 +621,7 @@ static device_method_t nfsmbsub_methods[] = { DEVMETHOD(smbus_readw, nfsmb_readw), DEVMETHOD(smbus_bwrite, nfsmb_bwrite), DEVMETHOD(smbus_bread, nfsmb_bread), - { 0, 0 } + DEVMETHOD_END }; static driver_t nfsmb_driver = { diff --git a/sys/dev/ntb/ntb_hw/ntb_hw_amd.c b/sys/dev/ntb/ntb_hw/ntb_hw_amd.c index fc3c6559d76a..24a507c47a57 100644 --- a/sys/dev/ntb/ntb_hw/ntb_hw_amd.c +++ b/sys/dev/ntb/ntb_hw/ntb_hw_amd.c @@ -465,7 +465,7 @@ amd_ntb_mw_set_wc(device_t dev, unsigned int mw_idx, vm_memattr_t mode) if (mode == bar_info->map_mode) return (0); - rc = pmap_change_attr((vm_offset_t)bar_info->vbase, bar_info->size, mode); + rc = pmap_change_attr(bar_info->vbase, bar_info->size, mode); if (rc == 0) bar_info->map_mode = mode; diff --git a/sys/dev/ntb/ntb_hw/ntb_hw_intel.c b/sys/dev/ntb/ntb_hw/ntb_hw_intel.c index d4852917085d..aa6c36e9c46e 100644 --- a/sys/dev/ntb/ntb_hw/ntb_hw_intel.c +++ b/sys/dev/ntb/ntb_hw/ntb_hw_intel.c @@ -1056,7 +1056,7 @@ map_memory_window_bar(struct ntb_softc *ntb, struct ntb_pci_bar_info *bar) if (mapmode == bar->map_mode) return (0); - rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size, mapmode); + rc = pmap_change_attr(bar->vbase, bar->size, mapmode); if (rc == 0) { bar->map_mode = mapmode; device_printf(ntb->device, @@ -3730,7 +3730,7 @@ intel_ntb_mw_set_wc_internal(struct ntb_softc *ntb, unsigned idx, vm_memattr_t m if (bar->map_mode == mode) return (0); - rc = pmap_change_attr((vm_offset_t)bar->vbase, bar->size, mode); + rc = pmap_change_attr(bar->vbase, bar->size, mode); if (rc == 0) bar->map_mode = mode; diff --git a/sys/dev/ntb/ntb_hw/ntb_hw_plx.c b/sys/dev/ntb/ntb_hw/ntb_hw_plx.c index 906660116067..01b5186bb7d1 100644 --- a/sys/dev/ntb/ntb_hw/ntb_hw_plx.c +++ b/sys/dev/ntb/ntb_hw/ntb_hw_plx.c @@ -860,7 +860,7 @@ ntb_plx_mw_set_wc(device_t dev, unsigned mw_idx, vm_memattr_t mode) split = (mw->mw_bar == 2) ? sc->split : 0; ss = (mw->mw_size - off) >> split; - rc = pmap_change_attr((vm_offset_t)mw->mw_vbase + off + ss * sp, + rc = pmap_change_attr(mw->mw_vbase + off + ss * sp, ss, mode); if (rc == 0) mw->splits[sp].mw_map_mode = mode; diff --git a/sys/dev/nvd/nvd.c b/sys/dev/nvd/nvd.c index 29c1e012bf24..1b32af2c6e4e 100644 --- a/sys/dev/nvd/nvd.c +++ b/sys/dev/nvd/nvd.c @@ -627,7 +627,7 @@ static device_method_t nvdc_methods[] = { DEVMETHOD(nvme_ns_changed, nvdc_ns_changed), DEVMETHOD(nvme_controller_failed, nvdc_controller_failed), DEVMETHOD(nvme_handle_aen, nvdc_handle_aen), - { 0, 0 } + DEVMETHOD_END }; static driver_t nvdc_driver = { diff --git a/sys/dev/nvdimm/nvdimm_var.h b/sys/dev/nvdimm/nvdimm_var.h index ad931e8fbb23..6b7c8afe42b3 100644 --- a/sys/dev/nvdimm/nvdimm_var.h +++ b/sys/dev/nvdimm/nvdimm_var.h @@ -79,7 +79,7 @@ _Static_assert(sizeof(struct nvdimm_label) == 256, "Incorrect layout"); typedef uint32_t nfit_handle_t; enum nvdimm_acpi_ivar { - NVDIMM_ROOT_IVAR_ACPI_HANDLE, + NVDIMM_ROOT_IVAR_ACPI_HANDLE = BUS_IVARS_PRIVATE, NVDIMM_ROOT_IVAR_DEVICE_HANDLE, NVDIMM_ROOT_IVAR_MAX, }; diff --git a/sys/dev/nvme/nvme_ahci.c b/sys/dev/nvme/nvme_ahci.c index b06661226d34..8be3887d835e 100644 --- a/sys/dev/nvme/nvme_ahci.c +++ b/sys/dev/nvme/nvme_ahci.c @@ -43,7 +43,7 @@ static device_method_t nvme_ahci_methods[] = { DEVMETHOD(device_attach, nvme_ahci_attach), DEVMETHOD(device_detach, nvme_ahci_detach), DEVMETHOD(device_shutdown, nvme_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t nvme_ahci_driver = { @@ -77,9 +77,6 @@ nvme_ahci_attach(device_t dev) ret = ENOMEM; goto bad; } - ctrlr->bus_tag = rman_get_bustag(ctrlr->resource); - ctrlr->bus_handle = rman_get_bushandle(ctrlr->resource); - ctrlr->regs = (struct nvme_registers *)ctrlr->bus_handle; /* Allocate and setup IRQ */ ctrlr->rid = 0; diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c index 7e1a3f02f326..753a8b380a75 100644 --- a/sys/dev/nvme/nvme_ctrlr.c +++ b/sys/dev/nvme/nvme_ctrlr.c @@ -782,6 +782,47 @@ nvme_ctrlr_configure_aer(struct nvme_controller *ctrlr) } static void +nvme_ctrlr_configure_apst(struct nvme_controller *ctrlr) +{ + struct nvme_completion_poll_status status; + uint64_t *data; + int data_size, i, read_size; + bool enable, error = true; + + if (TUNABLE_BOOL_FETCH("hw.nvme.apst_enable", &enable) == 0 || + ctrlr->cdata.apsta == 0) + return; + + data_size = 32 * sizeof(*data); + data = malloc(data_size, M_NVME, M_WAITOK | M_ZERO); + + if (getenv_array("hw.nvme.apst_data", data, data_size, + &read_size, sizeof(*data), GETENV_UNSIGNED) != 0) { + for (i = 0; i < read_size / sizeof(*data); ++i) + data[i] = htole64(data[i]); + } else { + status.done = 0; + nvme_ctrlr_cmd_get_feature(ctrlr, + NVME_FEAT_AUTONOMOUS_POWER_STATE_TRANSITION, 0, + data, data_size, nvme_completion_poll_cb, &status); + nvme_completion_poll(&status); + if (nvme_completion_is_error(&status.cpl)) + goto out; + } + + status.done = 0; + nvme_ctrlr_cmd_set_feature(ctrlr, + NVME_FEAT_AUTONOMOUS_POWER_STATE_TRANSITION, enable, 0, 0, + 0, 0, data, data_size, nvme_completion_poll_cb, &status); + nvme_completion_poll(&status); + error = nvme_completion_is_error(&status.cpl); +out: + if (error && bootverbose) + nvme_printf(ctrlr, "failed to configure APST\n"); + free(data, M_NVME); +} + +static void nvme_ctrlr_configure_int_coalescing(struct nvme_controller *ctrlr) { ctrlr->int_coal_time = 0; @@ -1047,6 +1088,7 @@ nvme_ctrlr_start(void *ctrlr_arg, bool resetting) } nvme_ctrlr_configure_aer(ctrlr); + nvme_ctrlr_configure_apst(ctrlr); nvme_ctrlr_configure_int_coalescing(ctrlr); for (i = 0; i < ctrlr->num_io_queues; i++) @@ -1304,29 +1346,51 @@ nvme_ctrlr_shared_handler(void *arg) #define NVME_MAX_PAGES (int)(1024 / sizeof(vm_page_t)) static int +nvme_page_count(vm_offset_t start, size_t len) +{ + return atop(round_page(start + len) - trunc_page(start)); +} + +static int nvme_user_ioctl_req(vm_offset_t addr, size_t len, bool is_read, - vm_page_t *upages, int max_pages, int *npagesp, struct nvme_request **req, + vm_page_t **upages, int max_pages, int *npagesp, struct nvme_request **req, nvme_cb_fn_t cb_fn, void *cb_arg) { vm_prot_t prot = VM_PROT_READ; - int err; + int err, npages; + vm_page_t *upages_us; + + upages_us = *upages; + npages = nvme_page_count(addr, len); + if (npages > atop(maxphys)) + return (EINVAL); + if (npages > max_pages) + upages_us = malloc(npages * sizeof(vm_page_t), M_NVME, + M_ZERO | M_WAITOK); if (is_read) prot |= VM_PROT_WRITE; /* Device will write to host memory */ err = vm_fault_hold_pages(&curproc->p_vmspace->vm_map, - addr, len, prot, upages, max_pages, npagesp); - if (err != 0) + addr, len, prot, upages_us, npages, npagesp); + if (err != 0) { + if (*upages != upages_us) + free(upages_us, M_NVME); return (err); + } *req = nvme_allocate_request_null(M_WAITOK, cb_fn, cb_arg); - (*req)->payload = memdesc_vmpages(upages, len, addr & PAGE_MASK); + (*req)->payload = memdesc_vmpages(upages_us, len, addr & PAGE_MASK); (*req)->payload_valid = true; + if (*upages != upages_us) + *upages = upages_us; return (0); } static void -nvme_user_ioctl_free(vm_page_t *pages, int npage) +nvme_user_ioctl_free(vm_page_t *pages, int npage, bool freeit) { vm_page_unhold_pages(pages, npage); + if (freeit) + free(pages, M_NVME); } static void @@ -1358,7 +1422,8 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, struct mtx *mtx; int ret = 0; int npages = 0; - vm_page_t upages[NVME_MAX_PAGES]; + vm_page_t upages_small[NVME_MAX_PAGES]; + vm_page_t *upages = upages_small; if (pt->len > 0) { if (pt->len > ctrlr->max_xfer_size) { @@ -1369,7 +1434,7 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, } if (is_user) { ret = nvme_user_ioctl_req((vm_offset_t)pt->buf, pt->len, - pt->is_read, upages, nitems(upages), &npages, &req, + pt->is_read, &upages, nitems(upages_small), &npages, &req, nvme_pt_done, pt); if (ret != 0) return (ret); @@ -1407,7 +1472,7 @@ nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr, mtx_unlock(mtx); if (npages > 0) - nvme_user_ioctl_free(upages, npages); + nvme_user_ioctl_free(upages, npages, upages != upages_small); return (ret); } @@ -1435,7 +1500,8 @@ nvme_ctrlr_linux_passthru_cmd(struct nvme_controller *ctrlr, struct mtx *mtx; int ret = 0; int npages = 0; - vm_page_t upages[NVME_MAX_PAGES]; + vm_page_t upages_small[NVME_MAX_PAGES]; + vm_page_t *upages = upages_small; /* * We don't support metadata. @@ -1452,8 +1518,8 @@ nvme_ctrlr_linux_passthru_cmd(struct nvme_controller *ctrlr, } if (is_user) { ret = nvme_user_ioctl_req(npc->addr, npc->data_len, - npc->opcode & 0x1, upages, nitems(upages), &npages, - &req, nvme_npc_done, npc); + npc->opcode & 0x1, &upages, nitems(upages_small), + &npages, &req, nvme_npc_done, npc); if (ret != 0) return (ret); } else @@ -1491,7 +1557,7 @@ nvme_ctrlr_linux_passthru_cmd(struct nvme_controller *ctrlr, mtx_unlock(mtx); if (npages > 0) - nvme_user_ioctl_free(upages, npages); + nvme_user_ioctl_free(upages, npages, upages != upages_small); return (ret); } @@ -1835,8 +1901,10 @@ nvme_ctrlr_submit_io_request(struct nvme_controller *ctrlr, struct nvme_request *req) { struct nvme_qpair *qpair; + int32_t ioq; - qpair = &ctrlr->ioq[QP(ctrlr, curcpu)]; + ioq = req->ioq == NVME_IOQ_DEFAULT ? QP(ctrlr, curcpu) : req->ioq; + qpair = &ctrlr->ioq[ioq]; nvme_qpair_submit_request(qpair, req); } diff --git a/sys/dev/nvme/nvme_ctrlr_cmd.c b/sys/dev/nvme/nvme_ctrlr_cmd.c index 5a44ed425acb..1a48a058edd8 100644 --- a/sys/dev/nvme/nvme_ctrlr_cmd.c +++ b/sys/dev/nvme/nvme_ctrlr_cmd.c @@ -171,7 +171,11 @@ nvme_ctrlr_cmd_set_feature(struct nvme_controller *ctrlr, uint8_t feature, struct nvme_request *req; struct nvme_command *cmd; - req = nvme_allocate_request_null(M_WAITOK, cb_fn, cb_arg); + if (payload != NULL) + req = nvme_allocate_request_vaddr(payload, payload_size, + M_WAITOK, cb_fn, cb_arg); + else + req = nvme_allocate_request_null(M_WAITOK, cb_fn, cb_arg); cmd = &req->cmd; cmd->opc = NVME_OPC_SET_FEATURES; @@ -193,7 +197,11 @@ nvme_ctrlr_cmd_get_feature(struct nvme_controller *ctrlr, uint8_t feature, struct nvme_request *req; struct nvme_command *cmd; - req = nvme_allocate_request_null(M_WAITOK, cb_fn, cb_arg); + if (payload != NULL) + req = nvme_allocate_request_vaddr(payload, payload_size, + M_WAITOK, cb_fn, cb_arg); + else + req = nvme_allocate_request_null(M_WAITOK, cb_fn, cb_arg); cmd = &req->cmd; cmd->opc = NVME_OPC_GET_FEATURES; diff --git a/sys/dev/nvme/nvme_pci.c b/sys/dev/nvme/nvme_pci.c index cecb05ca0a92..55cba580d6ca 100644 --- a/sys/dev/nvme/nvme_pci.c +++ b/sys/dev/nvme/nvme_pci.c @@ -54,7 +54,7 @@ static device_method_t nvme_pci_methods[] = { DEVMETHOD(device_suspend, nvme_pci_suspend), DEVMETHOD(device_resume, nvme_pci_resume), DEVMETHOD(device_shutdown, nvme_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t nvme_pci_driver = { @@ -151,24 +151,28 @@ nvme_pci_probe (device_t device) static int nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr) { + int error; + ctrlr->resource_id = PCIR_BAR(0); ctrlr->msix_table_resource_id = -1; ctrlr->msix_table_resource = NULL; ctrlr->msix_pba_resource_id = -1; ctrlr->msix_pba_resource = NULL; + /* + * Using RF_ACTIVE will set the Memory Space bit in the PCI command register. + * The remaining BARs will get mapped in before they've been programmed with + * an address. To avoid this we'll not set this flag and instead call + * bus_activate_resource() after all the BARs have been programmed. + */ ctrlr->resource = bus_alloc_resource_any(ctrlr->dev, SYS_RES_MEMORY, - &ctrlr->resource_id, RF_ACTIVE); + &ctrlr->resource_id, 0); if (ctrlr->resource == NULL) { nvme_printf(ctrlr, "unable to allocate pci resource\n"); return (ENOMEM); } - ctrlr->bus_tag = rman_get_bustag(ctrlr->resource); - ctrlr->bus_handle = rman_get_bushandle(ctrlr->resource); - ctrlr->regs = (struct nvme_registers *)ctrlr->bus_handle; - /* * The NVMe spec allows for the MSI-X tables to be placed behind * BAR 4 and/or 5, separate from the control/doorbell registers. @@ -180,7 +184,7 @@ nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr) if (ctrlr->msix_table_resource_id >= 0 && ctrlr->msix_table_resource_id != ctrlr->resource_id) { ctrlr->msix_table_resource = bus_alloc_resource_any(ctrlr->dev, - SYS_RES_MEMORY, &ctrlr->msix_table_resource_id, RF_ACTIVE); + SYS_RES_MEMORY, &ctrlr->msix_table_resource_id, 0); if (ctrlr->msix_table_resource == NULL) { nvme_printf(ctrlr, "unable to allocate msi-x table resource\n"); return (ENOMEM); @@ -190,13 +194,35 @@ nvme_ctrlr_allocate_bar(struct nvme_controller *ctrlr) ctrlr->msix_pba_resource_id != ctrlr->resource_id && ctrlr->msix_pba_resource_id != ctrlr->msix_table_resource_id) { ctrlr->msix_pba_resource = bus_alloc_resource_any(ctrlr->dev, - SYS_RES_MEMORY, &ctrlr->msix_pba_resource_id, RF_ACTIVE); + SYS_RES_MEMORY, &ctrlr->msix_pba_resource_id, 0); if (ctrlr->msix_pba_resource == NULL) { nvme_printf(ctrlr, "unable to allocate msi-x pba resource\n"); return (ENOMEM); } } + error = bus_activate_resource(ctrlr->dev, ctrlr->resource); + if (error) { + nvme_printf(ctrlr, "unable to activate pci resource: %d\n", error); + return (error); + } + if (ctrlr->msix_table_resource != NULL) { + error = bus_activate_resource(ctrlr->dev, ctrlr->msix_table_resource); + if (error) { + nvme_printf(ctrlr, "unable to activate msi-x table resource: %d\n", + error); + return (error); + } + } + if (ctrlr->msix_pba_resource != NULL) { + error = bus_activate_resource(ctrlr->dev, ctrlr->msix_pba_resource); + if (error) { + nvme_printf(ctrlr, "unable to activate msi-x pba resource: %d\n", + error); + return (error); + } + } + return (0); } diff --git a/sys/dev/nvme/nvme_private.h b/sys/dev/nvme/nvme_private.h index 8837275e2ed5..32c8cf91c1db 100644 --- a/sys/dev/nvme/nvme_private.h +++ b/sys/dev/nvme/nvme_private.h @@ -112,7 +112,9 @@ struct nvme_request { struct memdesc payload; nvme_cb_fn_t cb_fn; void *cb_arg; - int32_t retries; + int16_t retries; + uint16_t ioq; +#define NVME_IOQ_DEFAULT 0xffff bool payload_valid; bool timeout; bool spare[2]; /* Future use */ @@ -223,8 +225,6 @@ struct nvme_controller { #define QUIRK_INTEL_ALIGNMENT 4 /* Pre NVMe 1.3 performance alignment */ #define QUIRK_AHCI 8 /* Attached via AHCI redirect */ - bus_space_tag_t bus_tag; - bus_space_handle_t bus_handle; int resource_id; struct resource *resource; @@ -284,8 +284,6 @@ struct nvme_controller { struct nvme_qpair adminq; struct nvme_qpair *ioq; - struct nvme_registers *regs; - struct nvme_controller_data cdata; struct nvme_namespace ns[NVME_MAX_NAMESPACES]; @@ -298,8 +296,8 @@ struct nvme_controller { struct nvme_async_event_request aer[NVME_MAX_ASYNC_EVENTS]; uint32_t is_resetting; - u_int fail_on_reset; + bool fail_on_reset; bool is_failed; bool is_failed_admin; bool is_dying; @@ -328,20 +326,17 @@ struct nvme_controller { offsetof(struct nvme_registers, reg) #define nvme_mmio_read_4(sc, reg) \ - bus_space_read_4((sc)->bus_tag, (sc)->bus_handle, \ - nvme_mmio_offsetof(reg)) + bus_read_4((sc)->resource, nvme_mmio_offsetof(reg)) #define nvme_mmio_write_4(sc, reg, val) \ - bus_space_write_4((sc)->bus_tag, (sc)->bus_handle, \ - nvme_mmio_offsetof(reg), val) + bus_write_4((sc)->resource, nvme_mmio_offsetof(reg), val) #define nvme_mmio_write_8(sc, reg, val) \ do { \ - bus_space_write_4((sc)->bus_tag, (sc)->bus_handle, \ - nvme_mmio_offsetof(reg), val & 0xFFFFFFFF); \ - bus_space_write_4((sc)->bus_tag, (sc)->bus_handle, \ - nvme_mmio_offsetof(reg)+4, \ - (val & 0xFFFFFFFF00000000ULL) >> 32); \ + bus_write_4((sc)->resource, nvme_mmio_offsetof(reg), \ + (val) & 0xFFFFFFFF); \ + bus_write_4((sc)->resource, nvme_mmio_offsetof(reg) + 4, \ + ((val) & 0xFFFFFFFF00000000ULL) >> 32); \ } while (0); #define nvme_printf(ctrlr, fmt, args...) \ @@ -491,6 +486,7 @@ _nvme_allocate_request(const int how, nvme_cb_fn_t cb_fn, void *cb_arg) req = malloc(sizeof(*req), M_NVME, how | M_ZERO); if (req != NULL) { + req->ioq = NVME_IOQ_DEFAULT; req->cb_fn = cb_fn; req->cb_arg = cb_arg; req->timeout = true; @@ -499,11 +495,13 @@ _nvme_allocate_request(const int how, nvme_cb_fn_t cb_fn, void *cb_arg) } static __inline struct nvme_request * -nvme_allocate_request_vaddr(void *payload, uint32_t payload_size, +nvme_allocate_request_vaddr(void *payload, size_t payload_size, const int how, nvme_cb_fn_t cb_fn, void *cb_arg) { struct nvme_request *req; + KASSERT(payload_size <= UINT32_MAX, + ("payload size %zu exceeds maximum", payload_size)); req = _nvme_allocate_request(how, cb_fn, cb_arg); if (req != NULL) { req->payload = memdesc_vaddr(payload, payload_size); @@ -551,6 +549,22 @@ nvme_allocate_request_ccb(union ccb *ccb, const int how, nvme_cb_fn_t cb_fn, #define nvme_free_request(req) free(req, M_NVME) +static __inline void +nvme_request_set_ioq(struct nvme_controller *ctrlr, struct nvme_request *req, + uint16_t ioq) +{ + /* + * Note: NVMe queues are numbered 1-65535. The ioq here is numbered + * 0-65534 to avoid off-by-one bugs, with 65535 being reserved for + * DEFAULT. + */ + KASSERT(ioq == NVME_IOQ_DEFAULT || ioq < ctrlr->num_io_queues, + ("ioq %d out of range 0..%d", ioq, ctrlr->num_io_queues)); + if (ioq < 0 || ioq >= ctrlr->num_io_queues) + ioq = NVME_IOQ_DEFAULT; + req->ioq = ioq; +} + void nvme_notify_async(struct nvme_controller *ctrlr, const struct nvme_completion *async_cpl, uint32_t log_page_id, void *log_page_buffer, diff --git a/sys/dev/nvme/nvme_qpair.c b/sys/dev/nvme/nvme_qpair.c index 4f2c44da3b4f..e31bf818ed35 100644 --- a/sys/dev/nvme/nvme_qpair.c +++ b/sys/dev/nvme/nvme_qpair.c @@ -476,8 +476,8 @@ _nvme_qpair_process_completions(struct nvme_qpair *qpair) } if (done) { - bus_space_write_4(qpair->ctrlr->bus_tag, qpair->ctrlr->bus_handle, - qpair->cq_hdbl_off, qpair->cq_head); + bus_write_4(qpair->ctrlr->resource, qpair->cq_hdbl_off, + qpair->cq_head); } return (done); @@ -1068,8 +1068,7 @@ nvme_qpair_submit_tracker(struct nvme_qpair *qpair, struct nvme_tracker *tr) bus_dmamap_sync(qpair->dma_tag, qpair->queuemem_map, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); - bus_space_write_4(ctrlr->bus_tag, ctrlr->bus_handle, - qpair->sq_tdbl_off, qpair->sq_tail); + bus_write_4(ctrlr->resource, qpair->sq_tdbl_off, qpair->sq_tail); qpair->num_cmds++; } @@ -1209,7 +1208,7 @@ nvme_qpair_submit_request(struct nvme_qpair *qpair, struct nvme_request *req) static void nvme_qpair_enable(struct nvme_qpair *qpair) { - bool is_admin __unused = qpair == &qpair->ctrlr->adminq; + bool is_admin __diagused = qpair == &qpair->ctrlr->adminq; if (mtx_initialized(&qpair->recovery)) mtx_assert(&qpair->recovery, MA_OWNED); diff --git a/sys/dev/nvme/nvme_sim.c b/sys/dev/nvme/nvme_sim.c index 8b861cf3aa71..b9f09c8d1f61 100644 --- a/sys/dev/nvme/nvme_sim.c +++ b/sys/dev/nvme/nvme_sim.c @@ -343,7 +343,7 @@ nvme_sim_attach(device_t dev) sc->s_ctrlr = ctrlr; sc->s_sim = cam_sim_alloc(nvme_sim_action, nvme_sim_poll, - "nvme", sc, device_get_unit(dev), + "nvme", sc, device_get_unit(ctrlr->dev), NULL, max_trans, max_trans, devq); if (sc->s_sim == NULL) { device_printf(dev, "Failed to allocate a sim\n"); @@ -406,6 +406,16 @@ nvme_sim_ns_added(device_t dev, struct nvme_namespace *ns) union ccb *ccb; /* + * If we have no namespaces, then we both do not attach the nvme_sim_ns + * device. And then get a ns changed AER as well to tell us about it + * (which is how we get here). If there's no device attached, then + * there's nothing to do. sc->s_sim will be NULL as well (since it + * only gets set when we attach). + */ + if (!device_is_attached(dev)) + return (0); + + /* * We map the NVMe namespace idea onto the CAM unit LUN. For each new * namespace, scan or rescan the path to enumerate it. */ @@ -428,7 +438,7 @@ nvme_sim_ns_removed(device_t dev, struct nvme_namespace *ns) if (xpt_create_path(&tmppath, /*periph*/NULL, cam_sim_path(sc->s_sim), 0, ns->id) != CAM_REQ_CMP) { - printf("unable to create path for rescan\n"); + printf("unable to create path for ns removal\n"); return (ENOMEM); } xpt_async(AC_LOST_DEVICE, tmppath, NULL); @@ -476,7 +486,7 @@ static device_method_t nvme_sim_methods[] = { DEVMETHOD(nvme_ns_changed, nvme_sim_ns_changed), DEVMETHOD(nvme_controller_failed, nvme_sim_controller_failed), DEVMETHOD(nvme_handle_aen, nvme_sim_handle_aen), - { 0, 0 } + DEVMETHOD_END }; static driver_t nvme_sim_driver = { @@ -486,4 +496,4 @@ static driver_t nvme_sim_driver = { }; DRIVER_MODULE(nvme_sim, nvme, nvme_sim_driver, NULL, NULL); -MODULE_VERSION(nvme_shim, 1); +MODULE_VERSION(nvme_sim, 1); diff --git a/sys/dev/nvme/nvme_sysctl.c b/sys/dev/nvme/nvme_sysctl.c index 50d19e730a16..1b64ebddb9b2 100644 --- a/sys/dev/nvme/nvme_sysctl.c +++ b/sys/dev/nvme/nvme_sysctl.c @@ -425,7 +425,7 @@ nvme_sysctl_initialize_ctrlr(struct nvme_controller *ctrlr) CTLFLAG_RD, &ctrlr->cap_hi, 0, "Hi 32-bits of capacities for the drive"); - SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "fail_on_reset", + SYSCTL_ADD_BOOL(ctrlr_ctx, ctrlr_list, OID_AUTO, "fail_on_reset", CTLFLAG_RD, &ctrlr->fail_on_reset, 0, "Pretend the next reset fails and fail the controller"); diff --git a/sys/dev/nvmf/controller/nvmft_controller.c b/sys/dev/nvmf/controller/nvmft_controller.c index 1618c1f96dac..4c1b28b89265 100644 --- a/sys/dev/nvmf/controller/nvmft_controller.c +++ b/sys/dev/nvmf/controller/nvmft_controller.c @@ -227,7 +227,7 @@ nvmft_handoff_io_queue(struct nvmft_port *np, enum nvmf_trtype trtype, if (ctrlr == NULL) { mtx_unlock(&np->lock); printf("NVMFT: Nonexistent controller %u for I/O queue %u from %.*s\n", - ctrlr->cntlid, qid, (int)sizeof(data->hostnqn), + cntlid, qid, (int)sizeof(data->hostnqn), data->hostnqn); nvmft_connect_invalid_parameters(qp, cmd, true, offsetof(struct nvmf_fabric_connect_data, cntlid)); diff --git a/sys/dev/nvmf/nvmf.h b/sys/dev/nvmf/nvmf.h index 9b2b4c1dea40..e53eecca156e 100644 --- a/sys/dev/nvmf/nvmf.h +++ b/sys/dev/nvmf/nvmf.h @@ -27,11 +27,12 @@ #define NVMF_NN (1024) /* - * Default timeouts for Fabrics hosts. These match values used by + * Default settings for Fabrics hosts. These match values used by * Linux. */ #define NVMF_DEFAULT_RECONNECT_DELAY 10 #define NVMF_DEFAULT_CONTROLLER_LOSS 600 +#define NVMF_DEFAULT_IO_ENTRIES 128 /* * (data, size) is the userspace buffer for a packed nvlist. diff --git a/sys/dev/ofw/ofw_cpu.c b/sys/dev/ofw/ofw_cpu.c index 852ce6ea3759..7da34af6592a 100644 --- a/sys/dev/ofw/ofw_cpu.c +++ b/sys/dev/ofw/ofw_cpu.c @@ -43,7 +43,7 @@ #include <dev/ofw/ofw_bus_subr.h> #include <dev/ofw/ofw_cpu.h> -#if defined(__arm__) || defined(__arm64__) || defined(__riscv) +#if defined(__arm__) || defined(__aarch64__) || defined(__riscv) #include <dev/clk/clk.h> #define HAS_CLK #endif @@ -343,6 +343,11 @@ ofw_cpu_attach(device_t dev) if (sc->sc_cpu_pcpu == NULL) sc->sc_cpu_pcpu = pcpu_find(device_get_unit(dev)); +#ifdef HAS_CLK + clk_set_assigned(dev, node); + if (!OF_hasprop(node, "clocks")) { +#endif + if (OF_getencprop(node, "clock-frequency", &cell, sizeof(cell)) < 0) { if (get_freq_from_clk(dev, sc) != 0) { if (bootverbose) @@ -357,6 +362,10 @@ ofw_cpu_attach(device_t dev) sc->sc_nominal_mhz); OF_device_register_xref(OF_xref_from_node(node), dev); + +#ifdef HAS_CLK + } +#endif bus_identify_children(dev); bus_attach_children(dev); return (0); diff --git a/sys/dev/ofw/openfirm.c b/sys/dev/ofw/openfirm.c index b5f58b86a9c3..a8d3786ed152 100644 --- a/sys/dev/ofw/openfirm.c +++ b/sys/dev/ofw/openfirm.c @@ -381,11 +381,11 @@ OF_getproplen(phandle_t package, const char *propname) } /* Check existence of a property of a package. */ -int +bool OF_hasprop(phandle_t package, const char *propname) { - return (OF_getproplen(package, propname) >= 0 ? 1 : 0); + return (OF_getproplen(package, propname) >= 0); } /* Get the value of a property of a package. */ diff --git a/sys/dev/ofw/openfirm.h b/sys/dev/ofw/openfirm.h index 4e2b035827cb..fd13f4abd29e 100644 --- a/sys/dev/ofw/openfirm.h +++ b/sys/dev/ofw/openfirm.h @@ -108,7 +108,7 @@ ssize_t OF_getprop(phandle_t node, const char *propname, void *buf, size_t len); ssize_t OF_getencprop(phandle_t node, const char *prop, pcell_t *buf, size_t len); /* Same as getprop, but maintains endianness */ -int OF_hasprop(phandle_t node, const char *propname); +bool OF_hasprop(phandle_t node, const char *propname); ssize_t OF_searchprop(phandle_t node, const char *propname, void *buf, size_t len); ssize_t OF_searchencprop(phandle_t node, const char *propname, diff --git a/sys/dev/ow/ow.c b/sys/dev/ow/ow.c index 0325e6b324c8..493e22fdc8d2 100644 --- a/sys/dev/ow/ow.c +++ b/sys/dev/ow/ow.c @@ -706,7 +706,7 @@ static device_method_t ow_methods[] = { DEVMETHOD(own_acquire_bus, ow_acquire_bus), DEVMETHOD(own_release_bus, ow_release_bus), DEVMETHOD(own_crc, ow_crc), - { 0, 0 } + DEVMETHOD_END }; static driver_t ow_driver = { diff --git a/sys/dev/ow/ow.h b/sys/dev/ow/ow.h index b4d97f957504..6d38111d925c 100644 --- a/sys/dev/ow/ow.h +++ b/sys/dev/ow/ow.h @@ -27,7 +27,7 @@ #define DEV_OW_OW_H 1 enum ow_device_ivars { - OW_IVAR_FAMILY, + OW_IVAR_FAMILY = BUS_IVARS_PRIVATE, OW_IVAR_ROMID }; diff --git a/sys/dev/ow/ow_temp.c b/sys/dev/ow/ow_temp.c index 1fb5af2d53e8..1a5efbafab8a 100644 --- a/sys/dev/ow/ow_temp.c +++ b/sys/dev/ow/ow_temp.c @@ -266,7 +266,7 @@ static device_method_t ow_temp_methods[] = { DEVMETHOD(device_probe, ow_temp_probe), DEVMETHOD(device_attach, ow_temp_attach), DEVMETHOD(device_detach, ow_temp_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ow_temp_driver = { diff --git a/sys/dev/ow/owc_gpiobus.c b/sys/dev/ow/owc_gpiobus.c index f010a4dc75f1..a11570cccdf0 100644 --- a/sys/dev/ow/owc_gpiobus.c +++ b/sys/dev/ow/owc_gpiobus.c @@ -380,7 +380,7 @@ static device_method_t owc_gpiobus_methods[] = { DEVMETHOD(owll_write_zero, owc_gpiobus_write_zero), DEVMETHOD(owll_read_data, owc_gpiobus_read_data), DEVMETHOD(owll_reset_and_presence, owc_gpiobus_reset_and_presence), - { 0, 0 } + DEVMETHOD_END }; static driver_t owc_gpiobus_driver = { diff --git a/sys/dev/pbio/pbio.c b/sys/dev/pbio/pbio.c index 66fea479f5ac..662846210fae 100644 --- a/sys/dev/pbio/pbio.c +++ b/sys/dev/pbio/pbio.c @@ -121,7 +121,7 @@ static device_method_t pbio_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pbioprobe), DEVMETHOD(device_attach, pbioattach), - { 0, 0 } + DEVMETHOD_END }; static char driver_name[] = "pbio"; diff --git a/sys/dev/pccard/pccardvar.h b/sys/dev/pccard/pccardvar.h index 546d69939699..c6a03b242f35 100644 --- a/sys/dev/pccard/pccardvar.h +++ b/sys/dev/pccard/pccardvar.h @@ -191,7 +191,7 @@ int pccard_select_cfe(device_t dev, int entry); /* ivar interface */ enum { - PCCARD_IVAR_ETHADDR, /* read ethernet address from CIS tupple */ + PCCARD_IVAR_ETHADDR = BUS_IVARS_PRIVATE, /* read ethernet address from CIS tupple */ PCCARD_IVAR_VENDOR, PCCARD_IVAR_PRODUCT, PCCARD_IVAR_PRODEXT, diff --git a/sys/dev/pcf/pcf_isa.c b/sys/dev/pcf/pcf_isa.c index c797dc31e6d9..b2e9e6b61ede 100644 --- a/sys/dev/pcf/pcf_isa.c +++ b/sys/dev/pcf/pcf_isa.c @@ -78,7 +78,7 @@ static device_method_t pcf_isa_methods[] = { DEVMETHOD(iicbus_write, pcf_write), DEVMETHOD(iicbus_read, pcf_read), DEVMETHOD(iicbus_reset, pcf_rst_card), - { 0, 0 } + DEVMETHOD_END }; static driver_t pcf_isa_driver = { diff --git a/sys/dev/pci/controller/pci_n1sdp.c b/sys/dev/pci/controller/pci_n1sdp.c index 22f0ea27d45b..60664eec569e 100644 --- a/sys/dev/pci/controller/pci_n1sdp.c +++ b/sys/dev/pci/controller/pci_n1sdp.c @@ -83,7 +83,7 @@ static int n1sdp_init(struct generic_pcie_n1sdp_softc *sc) { struct pcie_discovery_data *shared_data; - vm_offset_t vaddr; + void *vaddr; vm_paddr_t paddr_rc; vm_paddr_t paddr; vm_page_t m[BDF_TABLE_SIZE / PAGE_SIZE]; @@ -101,7 +101,7 @@ n1sdp_init(struct generic_pcie_n1sdp_softc *sc) } vaddr = kva_alloc((vm_size_t)BDF_TABLE_SIZE); - if (vaddr == 0) { + if (vaddr == NULL) { printf("%s: Can't allocate KVA memory.", __func__); error = ENXIO; goto out; diff --git a/sys/dev/pci/fixup_pci.c b/sys/dev/pci/fixup_pci.c index cad175f301a3..1854b561e047 100644 --- a/sys/dev/pci/fixup_pci.c +++ b/sys/dev/pci/fixup_pci.c @@ -55,7 +55,7 @@ static void fixc1_nforce2(device_t dev); static device_method_t fixup_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, fixup_pci_probe), - { 0, 0 } + DEVMETHOD_END }; static driver_t fixup_pci_driver = { diff --git a/sys/dev/pci/hostb_pci.c b/sys/dev/pci/hostb_pci.c index f59211a14de9..dce64ffb4c17 100644 --- a/sys/dev/pci/hostb_pci.c +++ b/sys/dev/pci/hostb_pci.c @@ -275,7 +275,7 @@ static device_method_t pci_hostb_methods[] = { DEVMETHOD(pci_find_next_extcap, pci_hostb_find_next_extcap), DEVMETHOD(pci_find_htcap, pci_hostb_find_htcap), DEVMETHOD(pci_find_next_htcap, pci_hostb_find_next_htcap), - { 0, 0 } + DEVMETHOD_END }; static driver_t pci_hostb_driver = { diff --git a/sys/dev/pci/ignore_pci.c b/sys/dev/pci/ignore_pci.c index 8a12e43bcae3..7946c2017bd4 100644 --- a/sys/dev/pci/ignore_pci.c +++ b/sys/dev/pci/ignore_pci.c @@ -47,7 +47,7 @@ static device_method_t ignore_pci_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ignore_pci_probe), DEVMETHOD(device_attach, ignore_pci_attach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ignore_pci_driver = { diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index a46813cc155a..0dddd2dd263f 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -798,6 +798,9 @@ pci_fill_devinfo(device_t pcib, device_t bus, int d, int b, int s, int f, devlist_entry->conf.pc_progif = cfg->progif; devlist_entry->conf.pc_revid = cfg->revid; + devlist_entry->conf.pc_secbus = cfg->bridge.br_secbus; + devlist_entry->conf.pc_subbus = cfg->bridge.br_subbus; + pci_numdevs++; pci_generation++; diff --git a/sys/dev/pci/pci_dw.c b/sys/dev/pci/pci_dw.c index dcc9c0c5e369..7c9448a5593e 100644 --- a/sys/dev/pci/pci_dw.c +++ b/sys/dev/pci/pci_dw.c @@ -55,10 +55,10 @@ #include "pcib_if.h" #include "pci_dw_if.h" -#ifdef DEBUG -#define debugf(fmt, args...) do { printf(fmt,##args); } while (0) +#if 0 +#define dprintf(fmt, args...) do { printf(fmt,##args); } while (0) #else -#define debugf(fmt, args...) +#define dprintf(fmt, args...) #endif #define DBI_WR1(sc, reg, val) pci_dw_dbi_wr1((sc)->dev, reg, val) @@ -92,7 +92,7 @@ pci_dw_dbi_read(device_t dev, u_int reg, int width) sc = device_get_softc(dev); MPASS(sc->dbi_res != NULL); - + dprintf("%s: reg: 0x%04X, width: %d\n", __func__, reg, width); switch (width) { case 4: return (bus_read_4(sc->dbi_res, reg)); @@ -113,6 +113,8 @@ pci_dw_dbi_write(device_t dev, u_int reg, uint32_t val, int width) sc = device_get_softc(dev); MPASS(sc->dbi_res != NULL); + dprintf("%s: reg: 0x%04X, val: 0x%08X, width: %d\n", __func__, + reg, val, width); switch (width) { case 4: @@ -162,7 +164,7 @@ pci_dw_check_dev(struct pci_dw_softc *sc, u_int bus, u_int slot, u_int func, return (true); } - /* we have only 1 device with 1 function root port */ + /* we have only 1 device with 1 function on root port */ if (slot > 0 || func > 0) return (false); return (true); @@ -434,9 +436,14 @@ pci_dw_decode_ranges(struct pci_dw_softc *sc, struct ofw_pci_range *ranges, nmem = 0; for (i = 0; i < nranges; i++) { - if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) == - OFW_PCI_PHYS_HI_SPACE_MEM32) + switch (ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { + case OFW_PCI_PHYS_HI_SPACE_MEM32: + case OFW_PCI_PHYS_HI_SPACE_MEM64: ++nmem; + break; + default: + break; + } } sc->mem_ranges = malloc(nmem * sizeof(*sc->mem_ranges), M_DEVBUF, @@ -445,8 +452,9 @@ pci_dw_decode_ranges(struct pci_dw_softc *sc, struct ofw_pci_range *ranges, nmem = 0; for (i = 0; i < nranges; i++) { - if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) == - OFW_PCI_PHYS_HI_SPACE_IO) { + switch (ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { + + case OFW_PCI_PHYS_HI_SPACE_IO: if (sc->io_range.size != 0) { device_printf(sc->dev, "Duplicated IO range found in DT\n"); @@ -462,9 +470,10 @@ pci_dw_decode_ranges(struct pci_dw_softc *sc, struct ofw_pci_range *ranges, "trimming window size to 4GB\n"); sc->io_range.size = UINT32_MAX; } - } - if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) == - OFW_PCI_PHYS_HI_SPACE_MEM32) { + break; + + case OFW_PCI_PHYS_HI_SPACE_MEM32: + case OFW_PCI_PHYS_HI_SPACE_MEM64: MPASS(nmem < sc->num_mem_ranges); sc->mem_ranges[nmem] = ranges[i]; if (sc->mem_ranges[nmem].size > UINT32_MAX) { @@ -475,6 +484,13 @@ pci_dw_decode_ranges(struct pci_dw_softc *sc, struct ofw_pci_range *ranges, sc->mem_ranges[nmem].size = UINT32_MAX; } ++nmem; + break; + + default: + device_printf(sc->dev, + "%s: Unsupported range type (0x%X)\n", + __func__, ranges[i].pci_hi & + OFW_PCI_PHYS_HI_SPACEMASK); } } @@ -703,6 +719,7 @@ pci_dw_init(device_t dev) struct pci_dw_softc *sc; int rv, rid; bool unroll_mode; + u_int32_t br[2]; sc = device_get_softc(dev); sc->dev = dev; @@ -710,11 +727,30 @@ pci_dw_init(device_t dev) mtx_init(&sc->mtx, "pci_dw_mtx", NULL, MTX_DEF); - /* XXXn Should not be this configurable ? */ - sc->bus_start = 0; - sc->bus_end = 255; - sc->root_bus = 0; - sc->sub_bus = 1; + if (OF_hasprop(sc->node, "bus-range")) { + rv = OF_getencprop(sc->node, "bus-range", br, sizeof(br)); + if (rv < 0) { + device_printf(dev, + "Cannot read 'bus-range' property: %d\n", rv); + rv = ENXIO; + goto out; + } + if (rv != 8) { + device_printf(dev, + "Malformed 'bus-range' property: %d\n", rv); + rv = ENXIO; + goto out; + } + sc->bus_start = br[0]; + sc->bus_end = br[1]; + } else { + sc->bus_start = 0; + sc->bus_end = 255; + } + sc->root_bus = sc->bus_start; + sc->sub_bus = sc->bus_start + 1; + dprintf("%s: bus range[%d..%d], root bus %d, sub bus: %d\n", __func__, + sc->bus_end, sc->bus_start, sc->root_bus, sc->sub_bus); /* Read FDT properties */ if (!sc->coherent) @@ -724,6 +760,8 @@ pci_dw_init(device_t dev) sizeof(sc->num_lanes)); if (rv != sizeof(sc->num_lanes)) sc->num_lanes = 1; + dprintf("%s: num lanes: %d\n", __func__, sc->num_lanes); + if (sc->num_lanes != 1 && sc->num_lanes != 2 && sc->num_lanes != 4 && sc->num_lanes != 8) { device_printf(dev, @@ -769,7 +807,6 @@ pci_dw_init(device_t dev) &sc->dmat); if (rv != 0) goto out; - rv = ofw_pcib_init(dev); if (rv != 0) goto out; @@ -778,6 +815,9 @@ pci_dw_init(device_t dev) if (rv != 0) goto out; + dprintf("%s: version: 0x%08X, version type:0x%08X\n", __func__, + DBI_RD4(sc, DW_MISC_VERSION), DBI_RD4(sc, DW_MISC_VERSION_TYPE)); + unroll_mode = pci_dw_detect_atu_unroll(sc); if (bootverbose) device_printf(dev, "Using iATU %s mode\n", @@ -786,6 +826,7 @@ pci_dw_init(device_t dev) rid = 0; rv = ofw_bus_find_string_index(sc->node, "reg-names", "atu", &rid); if (rv == 0) { + dprintf("%s: Have 'atu' regs\n", __func__); sc->iatu_ur_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->iatu_ur_res == NULL) { @@ -798,6 +839,7 @@ pci_dw_init(device_t dev) sc->iatu_ur_offset = 0; sc->iatu_ur_size = rman_get_size(sc->iatu_ur_res); } else if (rv == ENOENT) { + dprintf("%s: Using 'dbi' regs for atu\n", __func__); sc->iatu_ur_res = sc->dbi_res; sc->iatu_ur_offset = DW_DEFAULT_IATU_UR_DBI_OFFSET; sc->iatu_ur_size = DW_DEFAULT_IATU_UR_DBI_SIZE; diff --git a/sys/dev/pci/pci_dw.h b/sys/dev/pci/pci_dw.h index 388eae86e40f..5b6f62ad6c84 100644 --- a/sys/dev/pci/pci_dw.h +++ b/sys/dev/pci/pci_dw.h @@ -61,6 +61,9 @@ #define DW_MISC_CONTROL_1 0x8BC #define DBI_RO_WR_EN (1 << 0) +#define DW_MISC_VERSION 0x8F8 +#define DW_MISC_VERSION_TYPE 0x8FC + /* Legacy (pre-4.80) iATU mode */ #define DW_IATU_VIEWPORT 0x900 #define IATU_REGION_INBOUND (1U << 31) diff --git a/sys/dev/pci/pci_iov.c b/sys/dev/pci/pci_iov.c index e0e47e11d401..0e6104fe37f2 100644 --- a/sys/dev/pci/pci_iov.c +++ b/sys/dev/pci/pci_iov.c @@ -735,16 +735,27 @@ pci_iov_config(struct cdev *cdev, struct pci_iov_arg *arg) last_rid = first_rid + (num_vfs - 1) * rid_stride; if (pci_get_bus(dev) != PCI_RID2BUS(last_rid)) { - int rid = 0; - uint16_t last_rid_bus = PCI_RID2BUS(last_rid); - - iov->iov_bus_res = bus_alloc_resource(bus, PCI_RES_BUS, &rid, - last_rid_bus, last_rid_bus, 1, RF_ACTIVE); - if (iov->iov_bus_res == NULL) { - device_printf(dev, - "failed to allocate PCIe bus number for VFs\n"); - error = ENOSPC; - goto out; + device_t pcib = device_get_parent(bus); + uint8_t secbus = pci_read_config(pcib, PCIR_SECBUS_1, 1); + uint8_t subbus = pci_read_config(pcib, PCIR_SUBBUS_1, 1); + uint16_t vf_bus = PCI_RID2BUS(last_rid); + + /* + * XXX: This should not be directly accessing the bridge registers and does + * nothing to prevent some other device from releasing this bus number while + * another PF is using it. + */ + if (secbus == 0 || vf_bus < secbus || vf_bus > subbus) { + int rid = 0; + + iov->iov_bus_res = bus_alloc_resource(bus, PCI_RES_BUS, &rid, + vf_bus, vf_bus, 1, RF_ACTIVE); + if (iov->iov_bus_res == NULL) { + device_printf(dev, + "failed to allocate PCIe bus number for VFs\n"); + error = ENOSPC; + goto out; + } } } diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c index 788af7339418..5cdb1de71c3f 100644 --- a/sys/dev/pci/pci_pci.c +++ b/sys/dev/pci/pci_pci.c @@ -437,6 +437,24 @@ pcib_alloc_window(struct pcib_softc *sc, struct pcib_window *w, int type, if (!pcib_is_window_open(w)) return; + /* + * Assume that a window where both the base and limit read as + * zero is not really open, or at least not assigned a valid + * range by the firmware. This can happen if a bridge device + * is never initialized by firmware, or if a platform driver + * resets the bridge. + * + * If devices behind this bridge have firmware-assigned + * resources in this range then the window will be reallocated + * on-demand. + */ + if (w->base == 0 && w->limit == ((pci_addr_t)1 << w->step) - 1) { + w->base = max_address; + w->limit = 0; + pcib_write_windows(sc, w->mask); + return; + } + if (w->base > max_address || w->limit > max_address) { device_printf(sc->dev, "initial %s window has too many bits, ignoring\n", w->name); diff --git a/sys/dev/pci/pci_user.c b/sys/dev/pci/pci_user.c index 9768030995e7..0e23363fba73 100644 --- a/sys/dev/pci/pci_user.c +++ b/sys/dev/pci/pci_user.c @@ -81,7 +81,9 @@ struct pci_conf32 { u_int32_t pd_unit; /* device unit number */ int pd_numa_domain; /* device NUMA domain */ u_int32_t pc_reported_len;/* length of PCI data reported */ - char pc_spare[64]; /* space for future fields */ + uint8_t pc_secbus; /* secondary bus number */ + uint8_t pc_subbus; /* subordinate bus number */ + char pc_spare[62]; /* space for future fields */ }; struct pci_match_conf32 { @@ -889,6 +891,8 @@ pci_conf_for_copyout(const struct pci_conf *pcp, union pci_conf_union *pcup, pcup->pc32.pd_unit = (uint32_t)pcp->pd_unit; if (cmd == PCIOCGETCONF32) { pcup->pc32.pd_numa_domain = pcp->pd_numa_domain; + pcup->pc32.pc_secbus = pcp->pc_secbus; + pcup->pc32.pc_subbus = pcp->pc_subbus; pcup->pc32.pc_reported_len = (uint32_t)offsetof(struct pci_conf32, pc_spare); } @@ -1315,6 +1319,32 @@ pci_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *t else dinfo->conf.pd_numa_domain = 0; + if (dinfo->cfg.dev != NULL) { + /* + * Re-read the values in case a driver + * changed them after the device was + * initially scanned. + */ + switch (dinfo->conf.pc_hdr) { + case PCIM_HDRTYPE_BRIDGE: + dinfo->conf.pc_secbus = + pci_read_config(dinfo->cfg.dev, + PCIR_SECBUS_1, 1); + dinfo->conf.pc_subbus = + pci_read_config(dinfo->cfg.dev, + PCIR_SUBBUS_1, 1); + break; + case PCIM_HDRTYPE_CARDBUS: + dinfo->conf.pc_secbus = + pci_read_config(dinfo->cfg.dev, + PCIR_SECBUS_2, 1); + dinfo->conf.pc_subbus = + pci_read_config(dinfo->cfg.dev, + PCIR_SUBBUS_2, 1); + break; + } + } + if (pattern_buf == NULL || pci_conf_match(cmd, pattern_buf, num_patterns, &dinfo->conf) == 0) { diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h index f6aaf30611e4..3ec7879b8a09 100644 --- a/sys/dev/pci/pcireg.h +++ b/sys/dev/pci/pcireg.h @@ -464,6 +464,7 @@ #define PCIP_SERIALBUS_USB_OHCI 0x10 #define PCIP_SERIALBUS_USB_EHCI 0x20 #define PCIP_SERIALBUS_USB_XHCI 0x30 +#define PCIP_SERIALBUS_USB_USB4 0x40 #define PCIP_SERIALBUS_USB_DEVICE 0xfe #define PCIS_SERIALBUS_FC 0x04 #define PCIS_SERIALBUS_SMBUS 0x05 diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 4abb5e977346..696e1c688c68 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -340,7 +340,7 @@ struct pci_devinfo { #include "pci_if.h" enum pci_device_ivars { - PCI_IVAR_SUBVENDOR, + PCI_IVAR_SUBVENDOR = BUS_IVARS_PRIVATE, PCI_IVAR_SUBDEVICE, PCI_IVAR_VENDOR, PCI_IVAR_DEVICE, @@ -414,7 +414,7 @@ pci_write_config(device_t dev, int reg, uint32_t val, int width) /*typedef enum pci_device_ivars pcib_device_ivars;*/ enum pcib_device_ivars { - PCIB_IVAR_DOMAIN, + PCIB_IVAR_DOMAIN = BUS_IVARS_PRIVATE, PCIB_IVAR_BUS }; diff --git a/sys/dev/pci/vga_pci.c b/sys/dev/pci/vga_pci.c index 23340696f0f0..39b2fcab67b4 100644 --- a/sys/dev/pci/vga_pci.c +++ b/sys/dev/pci/vga_pci.c @@ -746,7 +746,7 @@ static device_method_t vga_pci_methods[] = { DEVMETHOD(pci_release_msi, vga_pci_release_msi), DEVMETHOD(pci_msi_count, vga_pci_msi_count), DEVMETHOD(pci_msix_count, vga_pci_msix_count), - { 0, 0 } + DEVMETHOD_END }; static driver_t vga_pci_driver = { diff --git a/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c b/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c index cd1b80c3d712..25f822f73a37 100644 --- a/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c +++ b/sys/dev/pms/freebsd/driver/ini/src/agtiapi.c @@ -6586,7 +6586,7 @@ static device_method_t agtiapi_methods[] = { // Device interface DEVMETHOD( device_shutdown, agtiapi_shutdown ), DEVMETHOD( device_suspend, agtiapi_suspend ), DEVMETHOD( device_resume, agtiapi_resume ), - { 0, 0 } + DEVMETHOD_END }; static driver_t pmspcv_driver = { diff --git a/sys/dev/powermac_nvram/powermac_nvram.c b/sys/dev/powermac_nvram/powermac_nvram.c index ca7a7358bd4a..7f11bfa89ebb 100644 --- a/sys/dev/powermac_nvram/powermac_nvram.c +++ b/sys/dev/powermac_nvram/powermac_nvram.c @@ -74,7 +74,7 @@ static device_method_t powermac_nvram_methods[] = { DEVMETHOD(device_probe, powermac_nvram_probe), DEVMETHOD(device_attach, powermac_nvram_attach), DEVMETHOD(device_detach, powermac_nvram_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t powermac_nvram_driver = { diff --git a/sys/dev/ppbus/if_plip.c b/sys/dev/ppbus/if_plip.c index 16139139c0e7..22a8add2e55a 100644 --- a/sys/dev/ppbus/if_plip.c +++ b/sys/dev/ppbus/if_plip.c @@ -826,7 +826,7 @@ static device_method_t lp_methods[] = { DEVMETHOD(device_probe, lp_probe), DEVMETHOD(device_attach, lp_attach), DEVMETHOD(device_detach, lp_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t lp_driver = { diff --git a/sys/dev/ppbus/lpt.c b/sys/dev/ppbus/lpt.c index 401e94d25727..97f710d1216f 100644 --- a/sys/dev/ppbus/lpt.c +++ b/sys/dev/ppbus/lpt.c @@ -978,7 +978,7 @@ static device_method_t lpt_methods[] = { DEVMETHOD(device_probe, lpt_probe), DEVMETHOD(device_attach, lpt_attach), DEVMETHOD(device_detach, lpt_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t lpt_driver = { diff --git a/sys/dev/ppbus/pcfclock.c b/sys/dev/ppbus/pcfclock.c index 47a1a010a311..2cf8c0d4e271 100644 --- a/sys/dev/ppbus/pcfclock.c +++ b/sys/dev/ppbus/pcfclock.c @@ -321,7 +321,7 @@ static device_method_t pcfclock_methods[] = { DEVMETHOD(device_identify, pcfclock_identify), DEVMETHOD(device_probe, pcfclock_probe), DEVMETHOD(device_attach, pcfclock_attach), - { 0, 0 } + DEVMETHOD_END }; static driver_t pcfclock_driver = { diff --git a/sys/dev/ppbus/ppbconf.c b/sys/dev/ppbus/ppbconf.c index 2c3f17318747..c4931ca58172 100644 --- a/sys/dev/ppbus/ppbconf.c +++ b/sys/dev/ppbus/ppbconf.c @@ -574,7 +574,7 @@ static device_method_t ppbus_methods[] = { DEVMETHOD(bus_teardown_intr, ppbus_teardown_intr), DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), - { 0, 0 } + DEVMETHOD_END }; static driver_t ppbus_driver = { diff --git a/sys/dev/ppbus/ppbconf.h b/sys/dev/ppbus/ppbconf.h index 66f45634ea6d..673006bff4c6 100644 --- a/sys/dev/ppbus/ppbconf.h +++ b/sys/dev/ppbus/ppbconf.h @@ -178,7 +178,9 @@ struct ppb_context { /* * List of IVARS available to ppb device drivers */ -#define PPBUS_IVAR_MODE 0 +enum { + PPBUS_IVAR_MODE = BUS_IVARS_PRIVATE +}; /* other fields are reserved to the ppbus internals */ @@ -208,9 +210,11 @@ struct ppb_device { #define EPP_1_7 0x1 /* Parallel Port Chipset IVARS */ /* elsewhere XXX */ -#define PPC_IVAR_EPP_PROTO 0 -#define PPC_IVAR_LOCK 1 -#define PPC_IVAR_INTR_HANDLER 2 +enum { + PPC_IVAR_EPP_PROTO = BUS_IVARS_PRIVATE, + PPC_IVAR_LOCK, + PPC_IVAR_INTR_HANDLER +}; /* * Maximum size of the PnP info string diff --git a/sys/dev/ppbus/ppi.c b/sys/dev/ppbus/ppi.c index 3fd5f43a4a3a..3de63776210f 100644 --- a/sys/dev/ppbus/ppi.c +++ b/sys/dev/ppbus/ppi.c @@ -605,7 +605,7 @@ static device_method_t ppi_methods[] = { DEVMETHOD(device_probe, ppi_probe), DEVMETHOD(device_attach, ppi_attach), DEVMETHOD(device_detach, ppi_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t ppi_driver = { diff --git a/sys/dev/ppbus/pps.c b/sys/dev/ppbus/pps.c index 80581e3beae7..ed37b7e27231 100644 --- a/sys/dev/ppbus/pps.c +++ b/sys/dev/ppbus/pps.c @@ -332,7 +332,7 @@ static device_method_t pps_methods[] = { DEVMETHOD(device_identify, ppsidentify), DEVMETHOD(device_probe, ppsprobe), DEVMETHOD(device_attach, ppsattach), - { 0, 0 } + DEVMETHOD_END }; static driver_t pps_driver = { diff --git a/sys/dev/ppc/ppc_acpi.c b/sys/dev/ppc/ppc_acpi.c index a9d05cf7c2ff..41c34086f42f 100644 --- a/sys/dev/ppc/ppc_acpi.c +++ b/sys/dev/ppc/ppc_acpi.c @@ -79,7 +79,7 @@ static device_method_t ppc_acpi_methods[] = { #else DEVMETHOD(ppbus_write, ppc_write), #endif - { 0, 0 } + DEVMETHOD_END }; static driver_t ppc_acpi_driver = { diff --git a/sys/dev/ppc/ppc_isa.c b/sys/dev/ppc/ppc_isa.c index e1424295f239..907036bcc7ba 100644 --- a/sys/dev/ppc/ppc_isa.c +++ b/sys/dev/ppc/ppc_isa.c @@ -73,7 +73,7 @@ static device_method_t ppc_isa_methods[] = { DEVMETHOD(ppbus_ecp_sync, ppc_ecp_sync), DEVMETHOD(ppbus_read, ppc_read), DEVMETHOD(ppbus_write, ppc_isa_write), - { 0, 0 } + DEVMETHOD_END }; static driver_t ppc_isa_driver = { diff --git a/sys/dev/ppc/ppc_pci.c b/sys/dev/ppc/ppc_pci.c index d2fd2478fa7c..534ef40d8f37 100644 --- a/sys/dev/ppc/ppc_pci.c +++ b/sys/dev/ppc/ppc_pci.c @@ -64,7 +64,7 @@ static device_method_t ppc_pci_methods[] = { DEVMETHOD(ppbus_ecp_sync, ppc_ecp_sync), DEVMETHOD(ppbus_read, ppc_read), DEVMETHOD(ppbus_write, ppc_write), - { 0, 0 } + DEVMETHOD_END }; static driver_t ppc_pci_driver = { diff --git a/sys/dev/ppc/ppc_puc.c b/sys/dev/ppc/ppc_puc.c index b81e1dcfd45a..811ffb89fbb9 100644 --- a/sys/dev/ppc/ppc_puc.c +++ b/sys/dev/ppc/ppc_puc.c @@ -66,7 +66,7 @@ static device_method_t ppc_puc_methods[] = { DEVMETHOD(ppbus_ecp_sync, ppc_ecp_sync), DEVMETHOD(ppbus_read, ppc_read), DEVMETHOD(ppbus_write, ppc_write), - { 0, 0 } + DEVMETHOD_END }; static driver_t ppc_puc_driver = { diff --git a/sys/dev/pst/pst-pci.c b/sys/dev/pst/pst-pci.c index 3c1f740cf2f8..3815deef4039 100644 --- a/sys/dev/pst/pst-pci.c +++ b/sys/dev/pst/pst-pci.c @@ -118,7 +118,7 @@ static device_method_t pst_pci_methods[] = { DEVMETHOD(device_probe, iop_pci_probe), DEVMETHOD(device_attach, iop_pci_attach), DEVMETHOD(device_detach, iop_pci_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t pst_pci_driver = { diff --git a/sys/dev/pst/pst-raid.c b/sys/dev/pst/pst-raid.c index 3e98ed9eb1d2..5895ddfaa99e 100644 --- a/sys/dev/pst/pst-raid.c +++ b/sys/dev/pst/pst-raid.c @@ -368,7 +368,7 @@ bpack(int8_t *src, int8_t *dst, int len) static device_method_t pst_methods[] = { DEVMETHOD(device_probe, pst_probe), DEVMETHOD(device_attach, pst_attach), - { 0, 0 } + DEVMETHOD_END }; static driver_t pst_driver = { diff --git a/sys/dev/puc/puc_bus.h b/sys/dev/puc/puc_bus.h index 75c39a0f22fc..09fbe2dc42ab 100644 --- a/sys/dev/puc/puc_bus.h +++ b/sys/dev/puc/puc_bus.h @@ -32,8 +32,10 @@ #include <sys/serial.h> #include <serdev_if.h> -#define PUC_IVAR_CLOCK 0 -#define PUC_IVAR_TYPE 1 +enum { + PUC_IVAR_CLOCK = BUS_IVARS_PRIVATE, + PUC_IVAR_TYPE +}; /* Port types. */ #define PUC_TYPE_SERIAL 1 diff --git a/sys/dev/pwm/pwmbus.h b/sys/dev/pwm/pwmbus.h index 59aacc7beee4..172d8939bcf5 100644 --- a/sys/dev/pwm/pwmbus.h +++ b/sys/dev/pwm/pwmbus.h @@ -38,7 +38,7 @@ struct pwmbus_ivars { }; enum { - PWMBUS_IVAR_CHANNEL, /* Channel used by child dev */ + PWMBUS_IVAR_CHANNEL = BUS_IVARS_PRIVATE, /* Channel used by child dev */ }; #define PWMBUS_ACCESSOR(A, B, T) \ diff --git a/sys/dev/qcom_clk/qcom_clk_rcg2.c b/sys/dev/qcom_clk/qcom_clk_rcg2.c index 0407706dd138..6a1962982184 100644 --- a/sys/dev/qcom_clk/qcom_clk_rcg2.c +++ b/sys/dev/qcom_clk/qcom_clk_rcg2.c @@ -370,7 +370,7 @@ qcom_clk_rcg2_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout, device_printf(clknode_get_device(sc->clknode), "%s: no suitable freqtbl entry found for freq %llu\n", __func__, - *fout); + (unsigned long long) *fout); return (ERANGE); } @@ -475,7 +475,7 @@ qcom_clk_rcg2_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout, *fout, f->parent, f->freq, - p_freq); + (unsigned long long) p_freq); /* * To ensure glitch-free operation on some clocks, set it to @@ -547,7 +547,7 @@ qcom_clk_rcg2_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout, "%llu\n", __func__, f->parent, - p_freq); + (unsigned long long) p_freq); return (ENXIO); } @@ -570,7 +570,7 @@ qcom_clk_rcg2_set_freq(struct clknode *clk, uint64_t fin, uint64_t *fout, *fout, f->freq, f->parent, - p_freq); + (unsigned long long) p_freq); /* * Set the parent node, the parent programming and the divisor diff --git a/sys/dev/qcom_gcc/qcom_gcc_clock.c b/sys/dev/qcom_gcc/qcom_gcc_clock.c index c8c10b0c5172..f51b4021a821 100644 --- a/sys/dev/qcom_gcc/qcom_gcc_clock.c +++ b/sys/dev/qcom_gcc/qcom_gcc_clock.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2025, Adrian Chadd <adrian@FreeBSD.org> + * Copyright (c) 2026 Adrian Chadd <adrian@FreeBSD.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +37,7 @@ #include <machine/bus.h> #include <machine/resource.h> #include <sys/bus.h> +#include <sys/rman.h> #include <dev/fdt/fdt_common.h> #include <dev/ofw/ofw_bus.h> diff --git a/sys/dev/qcom_gcc/qcom_gcc_ipq4018_reset.c b/sys/dev/qcom_gcc/qcom_gcc_ipq4018_reset.c index f99d1d9ad9f1..127ca944c77e 100644 --- a/sys/dev/qcom_gcc/qcom_gcc_ipq4018_reset.c +++ b/sys/dev/qcom_gcc/qcom_gcc_ipq4018_reset.c @@ -38,6 +38,7 @@ #include <machine/bus.h> #include <machine/resource.h> +#include <sys/rman.h> #include <sys/bus.h> #include <dev/fdt/fdt_common.h> @@ -136,7 +137,8 @@ qcom_gcc_ipq4018_hwreset_assert(device_t dev, intptr_t id, bool reset) sc = device_get_softc(dev); if (id > nitems(gcc_ipq4019_reset_list)) { - device_printf(dev, "%s: invalid id (%d)\n", __func__, id); + device_printf(dev, "%s: invalid id (%d)\n", __func__, + (uint32_t) id); return (EINVAL); } @@ -160,7 +162,8 @@ qcom_gcc_ipq4018_hwreset_is_asserted(device_t dev, intptr_t id, bool *reset) sc = device_get_softc(dev); if (id > nitems(gcc_ipq4019_reset_list)) { - device_printf(dev, "%s: invalid id (%d)\n", __func__, id); + device_printf(dev, "%s: invalid id (%d)\n", __func__, + (uint32_t) id); return (EINVAL); } mtx_lock(&sc->mtx); @@ -171,7 +174,7 @@ qcom_gcc_ipq4018_hwreset_is_asserted(device_t dev, intptr_t id, bool *reset) *reset = false; mtx_unlock(&sc->mtx); - device_printf(dev, "called; id=%d\n", id); + device_printf(dev, "called; id=%d\n", (uint32_t) id); return (0); } diff --git a/sys/dev/qcom_gcc/qcom_gcc_main.c b/sys/dev/qcom_gcc/qcom_gcc_main.c index 3950bd985feb..38f409827541 100644 --- a/sys/dev/qcom_gcc/qcom_gcc_main.c +++ b/sys/dev/qcom_gcc/qcom_gcc_main.c @@ -1,7 +1,7 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * - * Copyright (c) 2025, Adrian Chadd <adrian@FreeBSD.org> + * Copyright (c) 2026 Adrian Chadd <adrian@FreeBSD.org> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -39,6 +39,7 @@ #include <machine/bus.h> #include <machine/resource.h> #include <sys/bus.h> +#include <sys/rman.h> #include <dev/fdt/fdt_common.h> #include <dev/ofw/ofw_bus.h> @@ -51,6 +52,7 @@ #include "qcom_gcc_var.h" #include "qcom_gcc_ipq4018.h" +#include "qcom_gcc_msm8916.h" static int qcom_gcc_modevent(module_t, int, void *); @@ -67,6 +69,8 @@ struct qcom_gcc_chipset_list_entry { static struct qcom_gcc_chipset_list_entry qcom_gcc_chipset_list[] = { { "qcom,gcc-ipq4019", "Qualcomm IPQ4018 Clock/Reset Controller", QCOM_GCC_CHIPSET_IPQ4018 }, + { "qcom,gcc-msm8916", "Qualcomm MSM8916 Clock/Reset Controller", + QCOM_GCC_CHIPSET_MSM8916 }, { NULL, NULL, 0 }, }; @@ -135,6 +139,10 @@ qcom_gcc_attach(device_t dev) qcom_gcc_ipq4018_hwreset_init(sc); mem_sz = 0x60000; break; + case QCOM_GCC_CHIPSET_MSM8916: + qcom_gcc_msm8916_hwreset_init(sc); + mem_sz = 0x0; + break; case QCOM_GCC_CHIPSET_NONE: device_printf(dev, "Invalid chipset (%d)\n", sc->sc_chipset); return (ENXIO); @@ -142,8 +150,13 @@ qcom_gcc_attach(device_t dev) sc->reg_rid = 0; - sc->reg = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY, - &sc->reg_rid, mem_sz, RF_ACTIVE); + if (mem_sz != 0) + sc->reg = bus_alloc_resource_anywhere(dev, SYS_RES_MEMORY, + &sc->reg_rid, mem_sz, RF_ACTIVE); + else + sc->reg = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->reg_rid, RF_ACTIVE); + if (sc->reg == NULL) { device_printf(dev, "Couldn't allocate memory resource!\n"); return (ENXIO); @@ -163,6 +176,9 @@ qcom_gcc_attach(device_t dev) case QCOM_GCC_CHIPSET_IPQ4018: qcom_gcc_ipq4018_clock_setup(sc); break; + case QCOM_GCC_CHIPSET_MSM8916: + qcom_gcc_msm8916_clock_setup(sc); + break; case QCOM_GCC_CHIPSET_NONE: device_printf(dev, "Invalid chipset (%d)\n", sc->sc_chipset); return (ENXIO); diff --git a/sys/dev/qcom_gcc/qcom_gcc_msm8916.h b/sys/dev/qcom_gcc/qcom_gcc_msm8916.h new file mode 100644 index 000000000000..10758b0744a4 --- /dev/null +++ b/sys/dev/qcom_gcc/qcom_gcc_msm8916.h @@ -0,0 +1,41 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Adrian Chadd <adrian@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __QCOM_GCC_MSM8916_H__ +#define __QCOM_GCC_MSM8916_H__ + +/* + * reset block + */ +extern void qcom_gcc_msm8916_hwreset_init(struct qcom_gcc_softc *); + +/* + * clock block + */ +extern void qcom_gcc_msm8916_clock_setup(struct qcom_gcc_softc *); + +#endif /* __QCOM_GCC_MSM8916_H__ */ diff --git a/sys/dev/qcom_gcc/qcom_gcc_msm8916_clock.c b/sys/dev/qcom_gcc/qcom_gcc_msm8916_clock.c new file mode 100644 index 000000000000..5c0e4afcc17f --- /dev/null +++ b/sys/dev/qcom_gcc/qcom_gcc_msm8916_clock.c @@ -0,0 +1,84 @@ +/*- + * Copyright (c) 2018 Ruslan Bukin <br@bsdpad.com> + * All rights reserved. + * + * This software was developed by BAE Systems, the University of Cambridge + * Computer Laboratory, and Memorial University under DARPA/AFRL contract + * FA8650-15-C-7558 ("CADETS"), as part of the DARPA Transparent Computing + * (TC) research program. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/kthread.h> +#include <sys/rman.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> + +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include "qcom_gcc_var.h" +#include "qcom_gcc_msm8916.h" + +#define GCC_QDSS_BCR 0x29000 +#define GCC_QDSS_BCR_BLK_ARES (1 << 0) /* Async software reset. */ +#define GCC_QDSS_CFG_AHB_CBCR 0x29008 +#define AHB_CBCR_CLK_ENABLE (1 << 0) /* AHB clk branch ctrl */ +#define GCC_QDSS_ETR_USB_CBCR 0x29028 +#define ETR_USB_CBCR_CLK_ENABLE (1 << 0) /* ETR USB clk branch ctrl */ +#define GCC_QDSS_DAP_CBCR 0x29084 +#define DAP_CBCR_CLK_ENABLE (1 << 0) /* DAP clk branch ctrl */ + +/* + * Qualcomm Debug Subsystem (QDSS) + * block enabling routine. + */ +static void +qcom_msm8916_qdss_enable(struct qcom_gcc_softc *sc) +{ + + /* Put QDSS block to reset */ + bus_write_4(sc->reg, GCC_QDSS_BCR, GCC_QDSS_BCR_BLK_ARES); + + /* Enable AHB clock branch */ + bus_write_4(sc->reg, GCC_QDSS_CFG_AHB_CBCR, AHB_CBCR_CLK_ENABLE); + + /* Enable DAP clock branch */ + bus_write_4(sc->reg, GCC_QDSS_DAP_CBCR, DAP_CBCR_CLK_ENABLE); + + /* Enable ETR USB clock branch */ + bus_write_4(sc->reg, GCC_QDSS_ETR_USB_CBCR, ETR_USB_CBCR_CLK_ENABLE); + + /* Out of reset */ + bus_write_4(sc->reg, GCC_QDSS_BCR, 0); +} + +void +qcom_gcc_msm8916_clock_setup(struct qcom_gcc_softc *sc) +{ + qcom_msm8916_qdss_enable(sc); +} diff --git a/sys/dev/qcom_gcc/qcom_gcc_msm8916_reset.c b/sys/dev/qcom_gcc/qcom_gcc_msm8916_reset.c new file mode 100644 index 000000000000..c83fd3e981ab --- /dev/null +++ b/sys/dev/qcom_gcc/qcom_gcc_msm8916_reset.c @@ -0,0 +1,71 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Adrian Chadd <adrian@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <sys/sglist.h> +#include <sys/random.h> +#include <sys/stdatomic.h> +#include <sys/mutex.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <sys/bus.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/hwreset/hwreset.h> + +#include "hwreset_if.h" + +#include "qcom_gcc_var.h" +#include "qcom_gcc_msm8916.h" + +static int +qcom_gcc_msm8916_hwreset_assert(device_t dev, intptr_t id, bool reset) +{ + device_printf(dev, "%s: invalid id (%d)\n", __func__, (uint32_t) id); + return (EINVAL); +} + +static int +qcom_gcc_msm8916_hwreset_is_asserted(device_t dev, intptr_t id, bool *reset) +{ + device_printf(dev, "%s: invalid id (%d)\n", __func__, (uint32_t) id); + return (EINVAL); +} + +void +qcom_gcc_msm8916_hwreset_init(struct qcom_gcc_softc *sc) +{ + sc->sc_cb.hw_reset_assert = qcom_gcc_msm8916_hwreset_assert; + sc->sc_cb.hw_reset_is_asserted = qcom_gcc_msm8916_hwreset_is_asserted; +} diff --git a/sys/dev/qcom_gcc/qcom_gcc_var.h b/sys/dev/qcom_gcc/qcom_gcc_var.h index 2d4e969e1134..e3796f0d5f0f 100644 --- a/sys/dev/qcom_gcc/qcom_gcc_var.h +++ b/sys/dev/qcom_gcc/qcom_gcc_var.h @@ -31,6 +31,7 @@ typedef enum { QCOM_GCC_CHIPSET_NONE = 0, QCOM_GCC_CHIPSET_IPQ4018 = 1, + QCOM_GCC_CHIPSET_MSM8916 = 2, } qcom_gcc_chipset_t; struct qcom_gcc_reset_entry { diff --git a/sys/dev/qcom_tlmm/qcom_tlmm.c b/sys/dev/qcom_tlmm/qcom_tlmm.c new file mode 100644 index 000000000000..3581e651fd59 --- /dev/null +++ b/sys/dev/qcom_tlmm/qcom_tlmm.c @@ -0,0 +1,237 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2025 Adrian Chadd <adrian@FreeBSD.org> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice unmodified, this list of conditions, and the following + * disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * This is a pinmux/gpio controller for the Qualcomm IPQ/MSM/Snapdragon SoCs. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> + +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/rman.h> +#include <sys/lock.h> +#include <sys/malloc.h> +#include <sys/mutex.h> +#include <sys/gpio.h> + +#include <machine/bus.h> +#include <machine/resource.h> +#include <dev/gpio/gpiobusvar.h> + +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> + +#include <dev/fdt/fdt_pinctrl.h> + +#include "qcom_tlmm_var.h" +#include "qcom_tlmm_pin.h" +#include "qcom_tlmm_debug.h" + +#include "gpio_if.h" + +#define DEFAULT_CAPS (GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | \ + GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN) + +/* TODO: put in a header file */ +extern void qcom_tlmm_ipq4018_attach(struct qcom_tlmm_softc *sc); + +struct qcom_tlmm_chipset_list { + qcom_tlmm_chipset_t id; + const char *ofw_str; + const char *desc_str; + void (*attach_func)(struct qcom_tlmm_softc *); +}; + +static struct qcom_tlmm_chipset_list qcom_tlmm_chipsets[] = { + { QCOM_TLMM_CHIPSET_IPQ4018, "qcom,ipq4019-pinctrl", + "Qualcomm Atheros TLMM IPQ4018/IPQ4019 GPIO/Pinmux driver", + qcom_tlmm_ipq4018_attach }, + { 0, NULL, NULL, NULL }, +}; + +static int +qcom_tlmm_probe(device_t dev) +{ + struct qcom_tlmm_softc *sc = device_get_softc(dev); + struct qcom_tlmm_chipset_list *ql; + int i; + + if (! ofw_bus_status_okay(dev)) + return (ENXIO); + + for (i = 0; qcom_tlmm_chipsets[i].id != 0; i++) { + ql = &qcom_tlmm_chipsets[i]; + device_printf(dev, "%s: checking %s\n", __func__, ql->ofw_str); + if (ofw_bus_is_compatible(dev, ql->ofw_str) == 1) { + sc->sc_chipset = ql->id; + sc->sc_attach_func = ql->attach_func; + device_set_desc(dev, ql->desc_str); + return (0); + } + } + + return (ENXIO); +} + +static int +qcom_tlmm_detach(device_t dev) +{ + struct qcom_tlmm_softc *sc = device_get_softc(dev); + + KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); + + gpiobus_detach_bus(dev); + if (sc->gpio_ih) + bus_teardown_intr(dev, sc->gpio_irq_res, sc->gpio_ih); + if (sc->gpio_irq_res) + bus_release_resource(dev, SYS_RES_IRQ, sc->gpio_irq_rid, + sc->gpio_irq_res); + if (sc->gpio_mem_res) + bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid, + sc->gpio_mem_res); + if (sc->gpio_pins) + free(sc->gpio_pins, M_DEVBUF); + mtx_destroy(&sc->gpio_mtx); + + return(0); +} + +static int +qcom_tlmm_attach(device_t dev) +{ + struct qcom_tlmm_softc *sc = device_get_softc(dev); + int i; + + KASSERT((device_get_unit(dev) == 0), + ("qcom_tlmm: Only one gpio module supported")); + + mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF); + + /* Map control/status registers. */ + sc->gpio_mem_rid = 0; + sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->gpio_mem_rid, RF_ACTIVE); + + if (sc->gpio_mem_res == NULL) { + device_printf(dev, "couldn't map memory\n"); + qcom_tlmm_detach(dev); + return (ENXIO); + } + + if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { + device_printf(dev, "unable to allocate IRQ resource\n"); + qcom_tlmm_detach(dev); + return (ENXIO); + } + + if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, + qcom_tlmm_filter, qcom_tlmm_intr, sc, &sc->gpio_ih))) { + device_printf(dev, + "WARNING: unable to register interrupt handler\n"); + qcom_tlmm_detach(dev); + return (ENXIO); + } + + sc->dev = dev; + sc->sc_debug = 0; + + /* Call platform specific attach function */ + sc->sc_attach_func(sc); + + qcom_tlmm_debug_sysctl_attach(sc); + + /* Allocate local pin state for all of our pins */ + sc->gpio_pins = malloc(sizeof(*sc->gpio_pins) * sc->gpio_npins, + M_DEVBUF, M_WAITOK | M_ZERO); + + /* Note: direct map between gpio pin and gpio_pin[] entry */ + for (i = 0; i < sc->gpio_npins; i++) { + snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, + "gpio%d", i); + sc->gpio_pins[i].gp_pin = i; + sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; + (void) qcom_tlmm_pin_getflags(dev, i, + &sc->gpio_pins[i].gp_flags); + } + + fdt_pinctrl_register(dev, NULL); + fdt_pinctrl_configure_by_name(dev, "default"); + + sc->busdev = gpiobus_add_bus(dev); + if (sc->busdev == NULL) { + device_printf(dev, "%s: failed to attach bus\n", __func__); + qcom_tlmm_detach(dev); + return (ENXIO); + } + bus_attach_children(dev); + + return (0); +} + +static device_method_t qcom_tlmm_methods[] = { + /* Driver */ + DEVMETHOD(device_probe, qcom_tlmm_probe), + DEVMETHOD(device_attach, qcom_tlmm_attach), + DEVMETHOD(device_detach, qcom_tlmm_detach), + + /* GPIO protocol */ + DEVMETHOD(gpio_get_bus, qcom_tlmm_get_bus), + DEVMETHOD(gpio_pin_max, qcom_tlmm_pin_max), + DEVMETHOD(gpio_pin_getname, qcom_tlmm_pin_getname), + DEVMETHOD(gpio_pin_getflags, qcom_tlmm_pin_getflags), + DEVMETHOD(gpio_pin_getcaps, qcom_tlmm_pin_getcaps), + DEVMETHOD(gpio_pin_setflags, qcom_tlmm_pin_setflags), + DEVMETHOD(gpio_pin_get, qcom_tlmm_pin_get), + DEVMETHOD(gpio_pin_set, qcom_tlmm_pin_set), + DEVMETHOD(gpio_pin_toggle, qcom_tlmm_pin_toggle), + + /* OFW */ + DEVMETHOD(ofw_bus_get_node, qcom_tlmm_pin_get_node), + + /* fdt_pinctrl interface */ + DEVMETHOD(fdt_pinctrl_configure, qcom_tlmm_pinctrl_configure), + + {0, 0}, +}; + +static driver_t qcom_tlmm_driver = { + "gpio", + qcom_tlmm_methods, + sizeof(struct qcom_tlmm_softc), +}; + +EARLY_DRIVER_MODULE(qcom_tlmm, simplebus, qcom_tlmm_driver, + NULL, NULL, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); +EARLY_DRIVER_MODULE(qcom_tlmm, ofwbus, qcom_tlmm_driver, + NULL, NULL, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); +MODULE_VERSION(qcom_tlmm, 1); diff --git a/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c b/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c index 50f54b896748..f6f00bdb1e1f 100644 --- a/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c +++ b/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c @@ -245,152 +245,34 @@ static const struct qcom_tlmm_gpio_mux gpio_muxes[] = { GDEF(-1), }; -static int -qcom_tlmm_ipq4018_probe(device_t dev) -{ - - if (! ofw_bus_status_okay(dev)) - return (ENXIO); - - if (ofw_bus_is_compatible(dev, "qcom,ipq4019-pinctrl") == 0) - return (ENXIO); - - device_set_desc(dev, - "Qualcomm Atheross TLMM IPQ4018/IPQ4019 GPIO/Pinmux driver"); - return (0); -} - -static int -qcom_tlmm_ipq4018_detach(device_t dev) -{ - struct qcom_tlmm_softc *sc = device_get_softc(dev); - - KASSERT(mtx_initialized(&sc->gpio_mtx), ("gpio mutex not initialized")); - - gpiobus_detach_bus(dev); - if (sc->gpio_ih) - bus_teardown_intr(dev, sc->gpio_irq_res, sc->gpio_ih); - if (sc->gpio_irq_res) - bus_release_resource(dev, SYS_RES_IRQ, sc->gpio_irq_rid, - sc->gpio_irq_res); - if (sc->gpio_mem_res) - bus_release_resource(dev, SYS_RES_MEMORY, sc->gpio_mem_rid, - sc->gpio_mem_res); - if (sc->gpio_pins) - free(sc->gpio_pins, M_DEVBUF); - mtx_destroy(&sc->gpio_mtx); - - return(0); -} - +static struct qcom_tlmm_hw_callbacks qcom_tlmm_ipq4018_hw_callbacks = { + .qcom_tlmm_hw_pin_set_function = qcom_tlmm_ipq4018_hw_pin_set_function, + .qcom_tlmm_hw_pin_get_function = qcom_tlmm_ipq4018_hw_pin_get_function, + .qcom_tlmm_hw_pin_set_oe_output = qcom_tlmm_ipq4018_hw_pin_set_oe_output, + .qcom_tlmm_hw_pin_set_oe_input = qcom_tlmm_ipq4018_hw_pin_set_oe_input, + .qcom_tlmm_hw_pin_get_oe_state = qcom_tlmm_ipq4018_hw_pin_get_oe_state, + .qcom_tlmm_hw_pin_set_output_value = qcom_tlmm_ipq4018_hw_pin_set_output_value, + .qcom_tlmm_hw_pin_get_output_value = qcom_tlmm_ipq4018_hw_pin_get_output_value, + .qcom_tlmm_hw_pin_get_input_value = qcom_tlmm_ipq4018_hw_pin_get_input_value, + .qcom_tlmm_hw_pin_toggle_output_value = qcom_tlmm_ipq4018_hw_pin_toggle_output_value, + .qcom_tlmm_hw_pin_set_pupd_config = qcom_tlmm_ipq4018_hw_pin_set_pupd_config, + .qcom_tlmm_hw_pin_get_pupd_config = qcom_tlmm_ipq4018_hw_pin_get_pupd_config, + .qcom_tlmm_hw_pin_set_drive_strength = qcom_tlmm_ipq4018_hw_pin_set_drive_strength, + .qcom_tlmm_hw_pin_get_drive_strength = qcom_tlmm_ipq4018_hw_pin_get_drive_strength, + .qcom_tlmm_hw_pin_set_vm = qcom_tlmm_ipq4018_hw_pin_set_vm, + .qcom_tlmm_hw_pin_get_vm = qcom_tlmm_ipq4018_hw_pin_get_vm, + .qcom_tlmm_hw_pin_set_open_drain = qcom_tlmm_ipq4018_hw_pin_set_open_drain, + .qcom_tlmm_hw_pin_get_open_drain = qcom_tlmm_ipq4018_hw_pin_get_open_drain, +}; +/* TODO: move to a header file */ +extern void qcom_tlmm_ipq4018_attach(struct qcom_tlmm_softc *sc); -static int -qcom_tlmm_ipq4018_attach(device_t dev) +void +qcom_tlmm_ipq4018_attach(struct qcom_tlmm_softc *sc) { - struct qcom_tlmm_softc *sc = device_get_softc(dev); - int i; - - KASSERT((device_get_unit(dev) == 0), - ("qcom_tlmm_ipq4018: Only one gpio module supported")); - - mtx_init(&sc->gpio_mtx, device_get_nameunit(dev), NULL, MTX_DEF); - - /* Map control/status registers. */ - sc->gpio_mem_rid = 0; - sc->gpio_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - &sc->gpio_mem_rid, RF_ACTIVE); - - if (sc->gpio_mem_res == NULL) { - device_printf(dev, "couldn't map memory\n"); - qcom_tlmm_ipq4018_detach(dev); - return (ENXIO); - } - if ((sc->gpio_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, - &sc->gpio_irq_rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { - device_printf(dev, "unable to allocate IRQ resource\n"); - qcom_tlmm_ipq4018_detach(dev); - return (ENXIO); - } - - if ((bus_setup_intr(dev, sc->gpio_irq_res, INTR_TYPE_MISC, - qcom_tlmm_filter, qcom_tlmm_intr, sc, &sc->gpio_ih))) { - device_printf(dev, - "WARNING: unable to register interrupt handler\n"); - qcom_tlmm_ipq4018_detach(dev); - return (ENXIO); - } - - sc->dev = dev; sc->gpio_npins = QCOM_TLMM_IPQ4018_GPIO_PINS; sc->gpio_muxes = &gpio_muxes[0]; - sc->sc_debug = 0; - - qcom_tlmm_debug_sysctl_attach(sc); - - /* Allocate local pin state for all of our pins */ - sc->gpio_pins = malloc(sizeof(*sc->gpio_pins) * sc->gpio_npins, - M_DEVBUF, M_WAITOK | M_ZERO); - - /* Note: direct map between gpio pin and gpio_pin[] entry */ - for (i = 0; i < sc->gpio_npins; i++) { - snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME, - "gpio%d", i); - sc->gpio_pins[i].gp_pin = i; - sc->gpio_pins[i].gp_caps = DEFAULT_CAPS; - (void) qcom_tlmm_pin_getflags(dev, i, - &sc->gpio_pins[i].gp_flags); - } - - fdt_pinctrl_register(dev, NULL); - fdt_pinctrl_configure_by_name(dev, "default"); - - sc->busdev = gpiobus_add_bus(dev); - if (sc->busdev == NULL) { - device_printf(dev, "%s: failed to attach bus\n", __func__); - qcom_tlmm_ipq4018_detach(dev); - return (ENXIO); - } - - bus_attach_children(dev); - return (0); + sc->sc_hw = &qcom_tlmm_ipq4018_hw_callbacks; } - -static device_method_t qcom_tlmm_ipq4018_methods[] = { - /* Driver */ - DEVMETHOD(device_probe, qcom_tlmm_ipq4018_probe), - DEVMETHOD(device_attach, qcom_tlmm_ipq4018_attach), - DEVMETHOD(device_detach, qcom_tlmm_ipq4018_detach), - - /* GPIO protocol */ - DEVMETHOD(gpio_get_bus, qcom_tlmm_get_bus), - DEVMETHOD(gpio_pin_max, qcom_tlmm_pin_max), - DEVMETHOD(gpio_pin_getname, qcom_tlmm_pin_getname), - DEVMETHOD(gpio_pin_getflags, qcom_tlmm_pin_getflags), - DEVMETHOD(gpio_pin_getcaps, qcom_tlmm_pin_getcaps), - DEVMETHOD(gpio_pin_setflags, qcom_tlmm_pin_setflags), - DEVMETHOD(gpio_pin_get, qcom_tlmm_pin_get), - DEVMETHOD(gpio_pin_set, qcom_tlmm_pin_set), - DEVMETHOD(gpio_pin_toggle, qcom_tlmm_pin_toggle), - - /* OFW */ - DEVMETHOD(ofw_bus_get_node, qcom_tlmm_pin_get_node), - - /* fdt_pinctrl interface */ - DEVMETHOD(fdt_pinctrl_configure, qcom_tlmm_pinctrl_configure), - - {0, 0}, -}; - -static driver_t qcom_tlmm_ipq4018_driver = { - "gpio", - qcom_tlmm_ipq4018_methods, - sizeof(struct qcom_tlmm_softc), -}; - -EARLY_DRIVER_MODULE(qcom_tlmm_ipq4018, simplebus, qcom_tlmm_ipq4018_driver, - NULL, NULL, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); -EARLY_DRIVER_MODULE(qcom_tlmm_ipq4018, ofwbus, qcom_tlmm_ipq4018_driver, - NULL, NULL, BUS_PASS_INTERRUPT + BUS_PASS_ORDER_LATE); -MODULE_VERSION(qcom_tlmm_ipq4018, 1); diff --git a/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018_hw.c b/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018_hw.c index 12aa1b7f8305..14d1055f195a 100644 --- a/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018_hw.c +++ b/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018_hw.c @@ -314,6 +314,7 @@ qcom_tlmm_ipq4018_hw_pin_set_pupd_config( reg |= QCOM_TLMM_IPQ4018_REG_PIN_CONTROL_PUPD_PULLDOWN << QCOM_TLMM_IPQ4018_REG_PIN_CONTROL_PUPD_SHIFT; break; + case QCOM_TLMM_PIN_PUPD_CONFIG_STRONG_PULL_UP: case QCOM_TLMM_PIN_PUPD_CONFIG_PULL_UP: reg |= QCOM_TLMM_IPQ4018_REG_PIN_CONTROL_PUPD_PULLUP << QCOM_TLMM_IPQ4018_REG_PIN_CONTROL_PUPD_SHIFT; diff --git a/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018_reg.h b/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018_reg.h index f1465ae28bb9..9507614fadc7 100644 --- a/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018_reg.h +++ b/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018_reg.h @@ -48,7 +48,7 @@ #define QCOM_TLMM_IPQ4018_REG_PIN_CONTROL_PUPD_PULLUP 2 /* There's no BUSHOLD on IPQ4018 */ #define QCOM_TLMM_IPQ4018_REG_PIN_CONTROL_PUPD_BUSHOLD 0 -#define QCOM_TLMM_IPQ4018_REG_PIN_CONTROL_MUX_MASK 0x7 +#define QCOM_TLMM_IPQ4018_REG_PIN_CONTROL_MUX_MASK 0xf #define QCOM_TLMM_IPQ4018_REG_PIN_CONTROL_MUX_SHIFT 2 /* function/mux control */ #define QCOM_TLMM_IPQ4018_REG_PIN_CONTROL_DRIVE_STRENGTH_SHIFT 6 diff --git a/sys/dev/qcom_tlmm/qcom_tlmm_pin.c b/sys/dev/qcom_tlmm/qcom_tlmm_pin.c index be7b37f21156..fcdcb20f6c95 100644 --- a/sys/dev/qcom_tlmm/qcom_tlmm_pin.c +++ b/sys/dev/qcom_tlmm/qcom_tlmm_pin.c @@ -85,11 +85,11 @@ qcom_tlmm_pin_configure(struct qcom_tlmm_softc *sc, * pin value before we flip on oe_output. */ pin->gp_flags |= GPIO_PIN_OUTPUT; - qcom_tlmm_ipq4018_hw_pin_set_oe_output(sc, + sc->sc_hw->qcom_tlmm_hw_pin_set_oe_output(sc, pin->gp_pin); } else { pin->gp_flags |= GPIO_PIN_INPUT; - qcom_tlmm_ipq4018_hw_pin_set_oe_input(sc, + sc->sc_hw->qcom_tlmm_hw_pin_set_oe_input(sc, pin->gp_pin); } } @@ -99,20 +99,21 @@ qcom_tlmm_pin_configure(struct qcom_tlmm_softc *sc, */ if (flags & GPIO_PIN_PULLUP) { pin->gp_flags |= GPIO_PIN_PULLUP; - qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, pin->gp_pin, + sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, pin->gp_pin, QCOM_TLMM_PIN_PUPD_CONFIG_PULL_UP); + /* XXX todo: i2c strong pull-up? */ } else if (flags & GPIO_PIN_PULLDOWN) { pin->gp_flags |= GPIO_PIN_PULLDOWN; - qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, pin->gp_pin, + sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, pin->gp_pin, QCOM_TLMM_PIN_PUPD_CONFIG_PULL_DOWN); } else if ((flags & (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) == (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN)) { pin->gp_flags |= GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN; - qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, pin->gp_pin, + sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, pin->gp_pin, QCOM_TLMM_PIN_PUPD_CONFIG_BUS_HOLD); } else { pin->gp_flags &= ~(GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN); - qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, pin->gp_pin, + sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, pin->gp_pin, QCOM_TLMM_PIN_PUPD_CONFIG_DISABLE); } } @@ -169,12 +170,12 @@ qcom_tlmm_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) GPIO_LOCK(sc); /* Lookup function - see what it is, whether we're a GPIO line */ - ret = qcom_tlmm_ipq4018_hw_pin_get_function(sc, pin, &val); + ret = sc->sc_hw->qcom_tlmm_hw_pin_get_function(sc, pin, &val); if (ret != 0) goto done; /* Lookup input/output state */ - ret = qcom_tlmm_ipq4018_hw_pin_get_oe_state(sc, pin, &is_output); + ret = sc->sc_hw->qcom_tlmm_hw_pin_get_oe_state(sc, pin, &is_output); if (ret != 0) goto done; if (is_output) @@ -183,7 +184,7 @@ qcom_tlmm_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) *flags |= GPIO_PIN_INPUT; /* Lookup pull-up / pull-down state */ - ret = qcom_tlmm_ipq4018_hw_pin_get_pupd_config(sc, pin, + ret = sc->sc_hw->qcom_tlmm_hw_pin_get_pupd_config(sc, pin, &pupd_config); if (ret != 0) goto done; @@ -197,6 +198,10 @@ qcom_tlmm_pin_getflags(device_t dev, uint32_t pin, uint32_t *flags) case QCOM_TLMM_PIN_PUPD_CONFIG_PULL_UP: *flags |= GPIO_PIN_PULLUP; break; + case QCOM_TLMM_PIN_PUPD_CONFIG_STRONG_PULL_UP: + /* XXX flag i2c "strong" pull-up? */ + *flags |= GPIO_PIN_PULLUP; + break; case QCOM_TLMM_PIN_PUPD_CONFIG_BUS_HOLD: *flags |= (GPIO_PIN_PULLUP | GPIO_PIN_PULLDOWN); break; @@ -251,7 +256,7 @@ qcom_tlmm_pin_set(device_t dev, uint32_t pin, unsigned int value) return (EINVAL); GPIO_LOCK(sc); - ret = qcom_tlmm_ipq4018_hw_pin_set_output_value(sc, pin, value); + ret = sc->sc_hw->qcom_tlmm_hw_pin_set_output_value(sc, pin, value); GPIO_UNLOCK(sc); return (ret); @@ -267,7 +272,7 @@ qcom_tlmm_pin_get(device_t dev, uint32_t pin, unsigned int *val) return (EINVAL); GPIO_LOCK(sc); - ret = qcom_tlmm_ipq4018_hw_pin_get_input_value(sc, pin, val); + ret = sc->sc_hw->qcom_tlmm_hw_pin_get_input_value(sc, pin, val); GPIO_UNLOCK(sc); return (ret); @@ -283,7 +288,7 @@ qcom_tlmm_pin_toggle(device_t dev, uint32_t pin) return (EINVAL); GPIO_LOCK(sc); - ret = qcom_tlmm_ipq4018_hw_pin_toggle_output_value(sc, pin); + ret = sc->sc_hw->qcom_tlmm_hw_pin_toggle_output_value(sc, pin); GPIO_UNLOCK(sc); return (ret); diff --git a/sys/dev/qcom_tlmm/qcom_tlmm_pinmux.c b/sys/dev/qcom_tlmm/qcom_tlmm_pinmux.c index a4b4dffa3dbb..59e97dfe7602 100644 --- a/sys/dev/qcom_tlmm/qcom_tlmm_pinmux.c +++ b/sys/dev/qcom_tlmm/qcom_tlmm_pinmux.c @@ -238,7 +238,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, __func__, gmux->id, tmp); - err = qcom_tlmm_ipq4018_hw_pin_set_function(sc, gmux->id, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_function(sc, gmux->id, tmp); if (err != 0) { device_printf(sc->dev, @@ -263,7 +263,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, cfg->params[i]); switch (i) { case PIN_ID_BIAS_DISABLE: - err = qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, gmux->id, QCOM_TLMM_PIN_PUPD_CONFIG_DISABLE); if (err != 0) { device_printf(sc->dev, @@ -274,7 +274,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_BIAS_PULL_DOWN: - err = qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, gmux->id, QCOM_TLMM_PIN_PUPD_CONFIG_PULL_DOWN); if (err != 0) { device_printf(sc->dev, @@ -285,7 +285,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_BIAS_BUS_HOLD: - err = qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, gmux->id, QCOM_TLMM_PIN_PUPD_CONFIG_BUS_HOLD); if (err != 0) { device_printf(sc->dev, @@ -297,7 +297,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, break; case PIN_ID_BIAS_PULL_UP: - err = qcom_tlmm_ipq4018_hw_pin_set_pupd_config(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_pupd_config(sc, gmux->id, QCOM_TLMM_PIN_PUPD_CONFIG_PULL_UP); if (err != 0) { device_printf(sc->dev, @@ -308,7 +308,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_OUTPUT_LOW: - err = qcom_tlmm_ipq4018_hw_pin_set_oe_output(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_oe_output(sc, gmux->id); if (err != 0) { device_printf(sc->dev, @@ -317,7 +317,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, __func__, gmux->id, err); goto done; } - err = qcom_tlmm_ipq4018_hw_pin_set_output_value( + err = sc->sc_hw->qcom_tlmm_hw_pin_set_output_value( sc, gmux->id, 0); if (err != 0) { device_printf(sc->dev, @@ -328,7 +328,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_OUTPUT_HIGH: - err = qcom_tlmm_ipq4018_hw_pin_set_oe_output(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_oe_output(sc, gmux->id); if (err != 0) { device_printf(sc->dev, @@ -337,7 +337,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, __func__, gmux->id, err); goto done; } - err = qcom_tlmm_ipq4018_hw_pin_set_output_value( + err = sc->sc_hw->qcom_tlmm_hw_pin_set_output_value( sc, gmux->id, 1); if (err != 0) { device_printf(sc->dev, @@ -348,7 +348,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_DRIVE_STRENGTH: - err = qcom_tlmm_ipq4018_hw_pin_set_drive_strength(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_drive_strength(sc, gmux->id, cfg->params[i]); if (err != 0) { device_printf(sc->dev, @@ -360,7 +360,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_VM_ENABLE: - err = qcom_tlmm_ipq4018_hw_pin_set_vm(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_vm(sc, gmux->id, true); if (err != 0) { device_printf(sc->dev, @@ -371,7 +371,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_VM_DISABLE: - err = qcom_tlmm_ipq4018_hw_pin_set_vm(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_vm(sc, gmux->id, false); if (err != 0) { device_printf(sc->dev, @@ -382,7 +382,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, } break; case PIN_ID_DRIVE_OPEN_DRAIN: - err = qcom_tlmm_ipq4018_hw_pin_set_open_drain(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_open_drain(sc, gmux->id, true); if (err != 0) { device_printf(sc->dev, @@ -394,7 +394,7 @@ qcom_tlmm_pinctrl_config_gmux(struct qcom_tlmm_softc *sc, char *pin_name, break; case PIN_ID_INPUT_ENABLE: /* Configure pin as an input */ - err = qcom_tlmm_ipq4018_hw_pin_set_oe_input(sc, + err = sc->sc_hw->qcom_tlmm_hw_pin_set_oe_input(sc, gmux->id); if (err != 0) { device_printf(sc->dev, diff --git a/sys/dev/qcom_tlmm/qcom_tlmm_var.h b/sys/dev/qcom_tlmm/qcom_tlmm_var.h index 1fea18275397..f9b9bcd9a3c8 100644 --- a/sys/dev/qcom_tlmm/qcom_tlmm_var.h +++ b/sys/dev/qcom_tlmm/qcom_tlmm_var.h @@ -49,6 +49,10 @@ #define GPIO_CLEAR_BITS(sc, reg, bits) \ GPIO_WRITE(sc, reg, GPIO_READ(sc, (reg)) & ~(bits)) +typedef enum { + QCOM_TLMM_CHIPSET_NONE = 0, + QCOM_TLMM_CHIPSET_IPQ4018 = 1, +} qcom_tlmm_chipset_t; enum prop_id { PIN_ID_BIAS_DISABLE = 0, @@ -91,6 +95,7 @@ typedef enum { QCOM_TLMM_PIN_PUPD_CONFIG_PULL_DOWN = 1, QCOM_TLMM_PIN_PUPD_CONFIG_PULL_UP = 2, QCOM_TLMM_PIN_PUPD_CONFIG_BUS_HOLD = 3, + QCOM_TLMM_PIN_PUPD_CONFIG_STRONG_PULL_UP = 4, /* i2c */ } qcom_tlmm_pin_pupd_config_t; @@ -141,6 +146,45 @@ struct qcom_tlmm_spec_pin { uint32_t hdrv_shift; }; +struct qcom_tlmm_softc; + +struct qcom_tlmm_hw_callbacks { + int (*qcom_tlmm_hw_pin_set_function)(struct qcom_tlmm_softc *, + int, int); + int (*qcom_tlmm_hw_pin_get_function)(struct qcom_tlmm_softc *, + int, int *); + int (*qcom_tlmm_hw_pin_set_oe_output)(struct qcom_tlmm_softc *, + int); + int (*qcom_tlmm_hw_pin_set_oe_input)(struct qcom_tlmm_softc *, + int); + int (*qcom_tlmm_hw_pin_get_oe_state)(struct qcom_tlmm_softc *, + int, bool *); + int (*qcom_tlmm_hw_pin_set_output_value)(struct qcom_tlmm_softc *, + uint32_t, unsigned int); + int (*qcom_tlmm_hw_pin_get_output_value)(struct qcom_tlmm_softc *, + uint32_t, unsigned int *); + int (*qcom_tlmm_hw_pin_get_input_value)(struct qcom_tlmm_softc *, + uint32_t, unsigned int *); + int (*qcom_tlmm_hw_pin_toggle_output_value)(struct qcom_tlmm_softc *, + uint32_t); + int (*qcom_tlmm_hw_pin_set_pupd_config)(struct qcom_tlmm_softc *, + uint32_t, qcom_tlmm_pin_pupd_config_t); + int (*qcom_tlmm_hw_pin_get_pupd_config)(struct qcom_tlmm_softc *, + uint32_t, qcom_tlmm_pin_pupd_config_t *); + int (*qcom_tlmm_hw_pin_set_drive_strength)(struct qcom_tlmm_softc *, + uint32_t, uint8_t); + int (*qcom_tlmm_hw_pin_get_drive_strength)(struct qcom_tlmm_softc *, + uint32_t, uint8_t *); + int (*qcom_tlmm_hw_pin_set_vm)(struct qcom_tlmm_softc *, + uint32_t, bool); + int (*qcom_tlmm_hw_pin_get_vm)(struct qcom_tlmm_softc *, + uint32_t, bool *); + int (*qcom_tlmm_hw_pin_set_open_drain)(struct qcom_tlmm_softc *, + uint32_t, bool); + int (*qcom_tlmm_hw_pin_get_open_drain)(struct qcom_tlmm_softc *, + uint32_t, bool *); +}; + struct qcom_tlmm_softc { device_t dev; device_t busdev; @@ -153,6 +197,10 @@ struct qcom_tlmm_softc { int gpio_npins; struct gpio_pin *gpio_pins; uint32_t sc_debug; + qcom_tlmm_chipset_t sc_chipset; + void (*sc_attach_func)(struct qcom_tlmm_softc *); + + struct qcom_tlmm_hw_callbacks *sc_hw; const struct qcom_tlmm_gpio_mux *gpio_muxes; const struct qcom_tlmm_spec_pin *spec_pins; diff --git a/sys/dev/qlnx/qlnxe/ecore_cxt.c b/sys/dev/qlnx/qlnxe/ecore_cxt.c index 6ace59ed68ce..153aa956396b 100644 --- a/sys/dev/qlnx/qlnxe/ecore_cxt.c +++ b/sys/dev/qlnx/qlnxe/ecore_cxt.c @@ -733,7 +733,7 @@ enum _ecore_status_t ecore_cxt_cfg_ilt_compute(struct ecore_hwfn *p_hwfn, * block in the ILT client. This is later used to * configure the CDU segment offset registers and * results in an FL command for TIDs of this - * segement behaves as regular load commands + * segment behaves as regular load commands * (loading TIDs from the working memory). */ line = p_cli->pf_blks[CDUT_SEG_BLK(i)].start_line; diff --git a/sys/dev/qlnx/qlnxe/ecore_l2.c b/sys/dev/qlnx/qlnxe/ecore_l2.c index ee7d225540d0..5e281c330765 100644 --- a/sys/dev/qlnx/qlnxe/ecore_l2.c +++ b/sys/dev/qlnx/qlnxe/ecore_l2.c @@ -1617,14 +1617,13 @@ ecore_sp_eth_filter_mcast(struct ecore_hwfn *p_hwfn, struct ecore_spq_comp_cb *p_comp_data) { struct vport_update_ramrod_data *p_ramrod = OSAL_NULL; - u32 bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; struct ecore_spq_entry *p_ent = OSAL_NULL; struct ecore_sp_init_data init_data; u8 abs_vport_id = 0; enum _ecore_status_t rc; int i; - if (p_filter_cmd->opcode == ECORE_FILTER_ADD) + if (p_filter_cmd->opcode == ECORE_FILTER_REPLACE) rc = ecore_fw_vport(p_hwfn, p_filter_cmd->vport_to_add_to, &abs_vport_id); else @@ -1654,30 +1653,33 @@ ecore_sp_eth_filter_mcast(struct ecore_hwfn *p_hwfn, /* explicitly clear out the entire vector */ OSAL_MEMSET(&p_ramrod->approx_mcast.bins, 0, sizeof(p_ramrod->approx_mcast.bins)); - OSAL_MEMSET(bins, 0, sizeof(u32) * ETH_MULTICAST_MAC_BINS_IN_REGS); - /* filter ADD op is explicit set op and it removes - * any existing filters for the vport. - */ - if (p_filter_cmd->opcode == ECORE_FILTER_ADD) { - for (i = 0; i < p_filter_cmd->num_mc_addrs; i++) { - u32 bit; - - bit = ecore_mcast_bin_from_mac(p_filter_cmd->mac[i]); - bins[bit / 32] |= 1 << (bit % 32); - } - + /* + * filter REPLACE op is explicit set op and it removes + * any existing filters for the vport. + */ + if (p_filter_cmd->opcode == ECORE_FILTER_REPLACE) { + _Static_assert(sizeof(p_filter_cmd->bins) == sizeof(p_ramrod->approx_mcast.bins), "Size mismatch"); + _Static_assert(nitems(p_filter_cmd->bins) == ETH_MULTICAST_MAC_BINS_IN_REGS, "Size mismatch"); /* Convert to correct endianity */ for (i = 0; i < ETH_MULTICAST_MAC_BINS_IN_REGS; i++) { struct vport_update_ramrod_mcast *p_ramrod_bins; p_ramrod_bins = &p_ramrod->approx_mcast; - p_ramrod_bins->bins[i] = OSAL_CPU_TO_LE32(bins[i]); + p_ramrod_bins->bins[i] = OSAL_CPU_TO_LE32(p_filter_cmd->bins[i]); } - } + } /* else FLUSH op clears existing filters */ p_ramrod->common.vport_id = abs_vport_id; rc = ecore_spq_post(p_hwfn, p_ent, OSAL_NULL); + + DP_INFO(p_hwfn, "Multicast filter cmd: [%s], bins: [%08x, %08x, %08x, %08x, %08x, %08x, %08x, %08x], ret = %d\n", + p_filter_cmd->opcode == ECORE_FILTER_REPLACE ? "replace" : "flush", + p_ramrod->approx_mcast.bins[0], p_ramrod->approx_mcast.bins[1], + p_ramrod->approx_mcast.bins[2], p_ramrod->approx_mcast.bins[3], + p_ramrod->approx_mcast.bins[4], p_ramrod->approx_mcast.bins[5], + p_ramrod->approx_mcast.bins[6], p_ramrod->approx_mcast.bins[7], rc); + if (rc != ECORE_SUCCESS) DP_ERR(p_hwfn, "Multicast filter command failed %d\n", rc); @@ -1692,10 +1694,9 @@ enum _ecore_status_t ecore_filter_mcast_cmd(struct ecore_dev *p_dev, enum _ecore_status_t rc = ECORE_SUCCESS; int i; - /* only ADD and REMOVE operations are supported for multi-cast */ - if ((p_filter_cmd->opcode != ECORE_FILTER_ADD && - (p_filter_cmd->opcode != ECORE_FILTER_REMOVE)) || - (p_filter_cmd->num_mc_addrs > ECORE_MAX_MC_ADDRS)) { + /* only REPLACE and FLUSH operations are supported for multi-cast */ + if ((p_filter_cmd->opcode != ECORE_FILTER_REPLACE && + (p_filter_cmd->opcode != ECORE_FILTER_FLUSH))) { return ECORE_INVAL; } diff --git a/sys/dev/qlnx/qlnxe/ecore_l2_api.h b/sys/dev/qlnx/qlnxe/ecore_l2_api.h index 610cc329f1fd..3b2f48e9fe11 100644 --- a/sys/dev/qlnx/qlnxe/ecore_l2_api.h +++ b/sys/dev/qlnx/qlnxe/ecore_l2_api.h @@ -162,14 +162,13 @@ struct ecore_filter_ucast { }; struct ecore_filter_mcast { - /* MOVE is not supported for multicast */ + /* Only REPLACE and FLUSH is supported for multicast */ enum ecore_filter_opcode opcode; u8 vport_to_add_to; u8 vport_to_remove_from; - u8 num_mc_addrs; -#define ECORE_MAX_MC_ADDRS 64 - unsigned char mac[ECORE_MAX_MC_ADDRS][ETH_ALEN]; + u32 bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; }; +#define ECORE_MAX_MC_ADDRS 64 struct ecore_filter_accept_flags { u8 update_rx_mode_config; @@ -384,7 +383,7 @@ struct ecore_sp_vport_update_params { u8 anti_spoofing_en; u8 update_accept_any_vlan_flg; u8 accept_any_vlan; - u32 bins[8]; + u32 bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; struct ecore_rss_params *rss_params; struct ecore_filter_accept_flags accept_flags; struct ecore_sge_tpa_params *sge_tpa_params; diff --git a/sys/dev/qlnx/qlnxe/ecore_vf.c b/sys/dev/qlnx/qlnxe/ecore_vf.c index 6cdc94d05c86..a7b006b982de 100644 --- a/sys/dev/qlnx/qlnxe/ecore_vf.c +++ b/sys/dev/qlnx/qlnxe/ecore_vf.c @@ -1515,18 +1515,13 @@ void ecore_vf_pf_filter_mcast(struct ecore_hwfn *p_hwfn, struct ecore_filter_mcast *p_filter_cmd) { struct ecore_sp_vport_update_params sp_params; - int i; OSAL_MEMSET(&sp_params, 0, sizeof(sp_params)); sp_params.update_approx_mcast_flg = 1; - if (p_filter_cmd->opcode == ECORE_FILTER_ADD) { - for (i = 0; i < p_filter_cmd->num_mc_addrs; i++) { - u32 bit; - - bit = ecore_mcast_bin_from_mac(p_filter_cmd->mac[i]); - sp_params.bins[bit / 32] |= 1 << (bit % 32); - } + if (p_filter_cmd->opcode == ECORE_FILTER_REPLACE) { + _Static_assert(sizeof(sp_params.bins) == sizeof(p_filter_cmd->bins), "Size mismatch"); + memcpy(sp_params.bins, p_filter_cmd->bins, sizeof(sp_params.bins)); } ecore_vf_pf_vport_update(p_hwfn, &sp_params); diff --git a/sys/dev/qlnx/qlnxe/qlnx_def.h b/sys/dev/qlnx/qlnxe/qlnx_def.h index 796845f3f8c6..f895487c47e4 100644 --- a/sys/dev/qlnx/qlnxe/qlnx_def.h +++ b/sys/dev/qlnx/qlnxe/qlnx_def.h @@ -319,7 +319,6 @@ typedef struct qlnx_link_output qlnx_link_output_t; #define QLNX_TPA_MAX_AGG_BUFFERS (20) -#define QLNX_MAX_NUM_MULTICAST_ADDRS ECORE_MAX_MC_ADDRS typedef struct _qlnx_mcast { uint16_t rsrvd; uint8_t addr[6]; @@ -370,7 +369,6 @@ struct qlnx_host { uint16_t device_id; if_t ifp; - int if_flags; volatile int link_up; struct ifmedia media; uint16_t max_frame_size; @@ -443,9 +441,7 @@ struct qlnx_host { qlnx_ivec_t irq_vec[QLNX_MAX_RSS]; uint8_t filter; - uint32_t nmcast; - qlnx_mcast_t mcast[QLNX_MAX_NUM_MULTICAST_ADDRS]; - struct ecore_filter_mcast ecore_mcast; + uint32_t ecore_mcast_bins[ETH_MULTICAST_MAC_BINS_IN_REGS]; uint8_t primary_mac[ETH_ALEN]; uint8_t prio_to_tc[MAX_NUM_PRI]; struct ecore_eth_stats hw_stats; @@ -683,7 +679,6 @@ extern int qlnx_grc_dump(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index); extern int qlnx_idle_chk(qlnx_host_t *ha, uint32_t *num_dumped_dwords, int hwfn_index); -extern uint8_t *qlnx_get_mac_addr(qlnx_host_t *ha); extern void qlnx_fill_link(qlnx_host_t *ha, struct ecore_hwfn *hwfn, struct qlnx_link_output *if_link); extern int qlnx_set_lldp_tlvx(qlnx_host_t *ha, qlnx_lldp_sys_tlvs_t *lldp_tlvs); diff --git a/sys/dev/qlnx/qlnxe/qlnx_os.c b/sys/dev/qlnx/qlnxe/qlnx_os.c index 99110e5e2d8f..215837968505 100644 --- a/sys/dev/qlnx/qlnxe/qlnx_os.c +++ b/sys/dev/qlnx/qlnxe/qlnx_os.c @@ -30,8 +30,6 @@ * Author : David C Somayajulu, Cavium, Inc., San Jose, CA 95131. */ -#include "opt_inet.h" - #include <sys/cdefs.h> #include "qlnx_os.h" #include "bcm_osal.h" @@ -50,6 +48,7 @@ #include "ecore_sp_commands.h" #include "ecore_dev_api.h" #include "ecore_l2_api.h" +#include "ecore_l2.h" #include "ecore_mcp.h" #include "ecore_hw_defs.h" #include "mcp_public.h" @@ -91,9 +90,9 @@ static void qlnx_fp_isr(void *arg); static void qlnx_init_ifnet(device_t dev, qlnx_host_t *ha); static void qlnx_init(void *arg); static void qlnx_init_locked(qlnx_host_t *ha); -static int qlnx_set_multi(qlnx_host_t *ha, uint32_t add_multi); -static int qlnx_set_promisc(qlnx_host_t *ha, int enabled); -static int qlnx_set_allmulti(qlnx_host_t *ha, int enabled); +static int qlnx_set_multi(qlnx_host_t *ha); +static int qlnx_set_promisc_allmulti(qlnx_host_t *ha, int flags); +static int _qlnx_set_promisc_allmulti(qlnx_host_t *ha, bool promisc, bool allmulti); static int qlnx_ioctl(if_t ifp, u_long cmd, caddr_t data); static int qlnx_media_change(if_t ifp); static void qlnx_media_status(if_t ifp, struct ifmediareq *ifmr); @@ -101,6 +100,7 @@ static void qlnx_stop(qlnx_host_t *ha); static int qlnx_send(qlnx_host_t *ha, struct qlnx_fastpath *fp, struct mbuf **m_headp); static int qlnx_get_ifq_snd_maxlen(qlnx_host_t *ha); +static void qlnx_get_mac_addr(qlnx_host_t *ha); static uint32_t qlnx_get_optics(qlnx_host_t *ha, struct qlnx_link_output *if_link); static int qlnx_transmit(if_t ifp, struct mbuf *mp); @@ -128,14 +128,13 @@ static void qlnx_set_id(struct ecore_dev *cdev, char name[NAME_SIZE], char ver_str[VER_SIZE]); static void qlnx_unload(qlnx_host_t *ha); static int qlnx_load(qlnx_host_t *ha); -static void qlnx_hw_set_multi(qlnx_host_t *ha, uint8_t *mta, uint32_t mcnt, - uint32_t add_mac); static void qlnx_dump_buf8(qlnx_host_t *ha, const char *msg, void *dbuf, uint32_t len); static int qlnx_alloc_rx_buffer(qlnx_host_t *ha, struct qlnx_rx_queue *rxq); static void qlnx_reuse_rx_data(struct qlnx_rx_queue *rxq); static void qlnx_update_rx_prod(struct ecore_hwfn *p_hwfn, struct qlnx_rx_queue *rxq); +static int qlnx_remove_all_mcast_mac(qlnx_host_t *ha); static int qlnx_set_rx_accept_filter(qlnx_host_t *ha, uint8_t filter); static int qlnx_grc_dumpsize(qlnx_host_t *ha, uint32_t *num_dwords, int hwfn_index); @@ -192,7 +191,7 @@ static device_method_t qlnx_pci_methods[] = { DEVMETHOD(pci_iov_uninit, qlnx_iov_uninit), DEVMETHOD(pci_iov_add_vf, qlnx_iov_add_vf), #endif /* #ifdef CONFIG_ECORE_SRIOV */ - { 0, 0 } + DEVMETHOD_END }; static driver_t qlnx_pci_driver = { @@ -212,7 +211,7 @@ static device_method_t qlnxv_pci_methods[] = { DEVMETHOD(device_probe, qlnx_pci_probe), DEVMETHOD(device_attach, qlnx_pci_attach), DEVMETHOD(device_detach, qlnx_pci_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t qlnxv_pci_driver = { @@ -2322,7 +2321,7 @@ qlnx_init_ifnet(device_t dev, qlnx_host_t *ha) ha->max_frame_size = if_getmtu(ifp) + ETHER_HDR_LEN + ETHER_CRC_LEN; - memcpy(ha->primary_mac, qlnx_get_mac_addr(ha), ETH_ALEN); + qlnx_get_mac_addr(ha); if (!ha->primary_mac[0] && !ha->primary_mac[1] && !ha->primary_mac[2] && !ha->primary_mac[3] && @@ -2392,8 +2391,6 @@ qlnx_init_ifnet(device_t dev, qlnx_host_t *ha) ifmedia_set(&ha->media, (IFM_ETHER | IFM_AUTO)); ether_ifattach(ifp, ha->primary_mac); - bcopy(if_getlladdr(ha->ifp), ha->primary_mac, ETHER_ADDR_LEN); - QL_DPRINT2(ha, "exit\n"); return; @@ -2432,7 +2429,8 @@ qlnx_init(void *arg) QL_DPRINT2(ha, "enter\n"); QLNX_LOCK(ha); - qlnx_init_locked(ha); + if ((if_getdrvflags(ha->ifp) & IFF_DRV_RUNNING) == 0) + qlnx_init_locked(ha); QLNX_UNLOCK(ha); QL_DPRINT2(ha, "exit\n"); @@ -2440,181 +2438,91 @@ qlnx_init(void *arg) return; } -static int -qlnx_config_mcast_mac_addr(qlnx_host_t *ha, uint8_t *mac_addr, uint32_t add_mac) -{ - struct ecore_filter_mcast *mcast; - struct ecore_dev *cdev; - int rc; - - cdev = &ha->cdev; - - mcast = &ha->ecore_mcast; - bzero(mcast, sizeof(struct ecore_filter_mcast)); - - if (add_mac) - mcast->opcode = ECORE_FILTER_ADD; - else - mcast->opcode = ECORE_FILTER_REMOVE; - - mcast->num_mc_addrs = 1; - memcpy(mcast->mac, mac_addr, ETH_ALEN); - - rc = ecore_filter_mcast_cmd(cdev, mcast, ECORE_SPQ_MODE_CB, NULL); - - return (rc); -} - -static int -qlnx_hw_add_mcast(qlnx_host_t *ha, uint8_t *mta) -{ - int i; - - for (i = 0; i < QLNX_MAX_NUM_MULTICAST_ADDRS; i++) { - if (QL_MAC_CMP(ha->mcast[i].addr, mta) == 0) - return 0; /* its been already added */ - } - - for (i = 0; i < QLNX_MAX_NUM_MULTICAST_ADDRS; i++) { - if ((ha->mcast[i].addr[0] == 0) && - (ha->mcast[i].addr[1] == 0) && - (ha->mcast[i].addr[2] == 0) && - (ha->mcast[i].addr[3] == 0) && - (ha->mcast[i].addr[4] == 0) && - (ha->mcast[i].addr[5] == 0)) { - if (qlnx_config_mcast_mac_addr(ha, mta, 1)) - return (-1); - - bcopy(mta, ha->mcast[i].addr, ETH_ALEN); - ha->nmcast++; - - return 0; - } - } - return 0; -} - -static int -qlnx_hw_del_mcast(qlnx_host_t *ha, uint8_t *mta) -{ - int i; - - for (i = 0; i < QLNX_MAX_NUM_MULTICAST_ADDRS; i++) { - if (QL_MAC_CMP(ha->mcast[i].addr, mta) == 0) { - if (qlnx_config_mcast_mac_addr(ha, mta, 0)) - return (-1); - - ha->mcast[i].addr[0] = 0; - ha->mcast[i].addr[1] = 0; - ha->mcast[i].addr[2] = 0; - ha->mcast[i].addr[3] = 0; - ha->mcast[i].addr[4] = 0; - ha->mcast[i].addr[5] = 0; - - ha->nmcast--; - - return 0; - } - } - return 0; -} - -/* - * Name: qls_hw_set_multi - * Function: Sets the Multicast Addresses provided the host O.S into the - * hardware (for the given interface) - */ -static void -qlnx_hw_set_multi(qlnx_host_t *ha, uint8_t *mta, uint32_t mcnt, - uint32_t add_mac) -{ - int i; - - for (i = 0; i < mcnt; i++) { - if (add_mac) { - if (qlnx_hw_add_mcast(ha, mta)) - break; - } else { - if (qlnx_hw_del_mcast(ha, mta)) - break; - } - - mta += ETHER_ADDR_LEN; - } - return; -} - static u_int -qlnx_copy_maddr(void *arg, struct sockaddr_dl *sdl, u_int mcnt) +qlnx_mcast_bins_from_maddr(void *arg, struct sockaddr_dl *sdl, u_int mcnt) { - uint8_t *mta = arg; + uint8_t bit; + uint32_t *bins = arg; - if (mcnt == QLNX_MAX_NUM_MULTICAST_ADDRS) - return (0); - - bcopy(LLADDR(sdl), &mta[mcnt * ETHER_ADDR_LEN], ETHER_ADDR_LEN); + bit = ecore_mcast_bin_from_mac(LLADDR(sdl)); + bins[bit / 32] |= 1 << (bit % 32); return (1); } static int -qlnx_set_multi(qlnx_host_t *ha, uint32_t add_multi) +qlnx_set_multi(qlnx_host_t *ha) { - uint8_t mta[QLNX_MAX_NUM_MULTICAST_ADDRS * ETHER_ADDR_LEN]; - if_t ifp = ha->ifp; - u_int mcnt; + struct ecore_filter_mcast mcast; + struct ecore_dev *cdev; + if_t ifp = ha->ifp; + u_int mcnt __unused; + int rc; if (qlnx_vf_device(ha) == 0) return (0); - mcnt = if_foreach_llmaddr(ifp, qlnx_copy_maddr, mta); + bzero(&mcast, sizeof(struct ecore_filter_mcast)); + mcnt = if_foreach_llmaddr(ifp, qlnx_mcast_bins_from_maddr, mcast.bins); + QL_DPRINT1(ha, "total %d multicast MACs found\n", mcnt); - QLNX_LOCK(ha); - qlnx_hw_set_multi(ha, mta, mcnt, add_multi); - QLNX_UNLOCK(ha); + if (memcmp(ha->ecore_mcast_bins, mcast.bins, sizeof(mcast.bins)) == 0) + return (0); - return (0); + cdev = &ha->cdev; + mcast.opcode = ECORE_FILTER_REPLACE; + rc = ecore_filter_mcast_cmd(cdev, &mcast, ECORE_SPQ_MODE_CB, NULL); + if (rc == 0) + memcpy(ha->ecore_mcast_bins, mcast.bins, sizeof(mcast.bins)); + + QL_DPRINT1(ha, "ecore_filter_mcast_cmd: end(%d)\n", rc); + return (rc); } static int -qlnx_set_promisc(qlnx_host_t *ha, int enabled) +qlnx_set_promisc_allmulti(qlnx_host_t *ha, int flags) { int rc = 0; - uint8_t filter; if (qlnx_vf_device(ha) == 0) return (0); - filter = ha->filter; - if (enabled) { - filter |= ECORE_ACCEPT_MCAST_UNMATCHED; - filter |= ECORE_ACCEPT_UCAST_UNMATCHED; - } else { - filter &= ~ECORE_ACCEPT_MCAST_UNMATCHED; - filter &= ~ECORE_ACCEPT_UCAST_UNMATCHED; - } - - rc = qlnx_set_rx_accept_filter(ha, filter); + rc = _qlnx_set_promisc_allmulti(ha, flags & IFF_PROMISC, + flags & IFF_ALLMULTI); return (rc); } static int -qlnx_set_allmulti(qlnx_host_t *ha, int enabled) +_qlnx_set_promisc_allmulti(qlnx_host_t *ha, bool promisc, bool allmulti) { int rc = 0; uint8_t filter; - - if (qlnx_vf_device(ha) == 0) - return (0); + bool mcast, ucast; filter = ha->filter; - if (enabled) { + filter |= ECORE_ACCEPT_UCAST_MATCHED; + filter |= ECORE_ACCEPT_MCAST_MATCHED; + filter |= ECORE_ACCEPT_BCAST; + + mcast = promisc || allmulti; + ucast = promisc; + + if (mcast) filter |= ECORE_ACCEPT_MCAST_UNMATCHED; - } else { + else filter &= ~ECORE_ACCEPT_MCAST_UNMATCHED; - } - rc = qlnx_set_rx_accept_filter(ha, filter); + if (ucast) + filter |= ECORE_ACCEPT_UCAST_UNMATCHED; + else + filter &= ~ECORE_ACCEPT_UCAST_UNMATCHED; + + if (filter == ha->filter) + return (0); + + rc = qlnx_set_rx_accept_filter(ha, filter); + if (rc == 0) + ha->filter = filter; return (rc); } @@ -2624,35 +2532,11 @@ qlnx_ioctl(if_t ifp, u_long cmd, caddr_t data) int ret = 0, mask; int flags; struct ifreq *ifr = (struct ifreq *)data; -#ifdef INET - struct ifaddr *ifa = (struct ifaddr *)data; -#endif qlnx_host_t *ha; ha = (qlnx_host_t *)if_getsoftc(ifp); switch (cmd) { - case SIOCSIFADDR: - QL_DPRINT4(ha, "SIOCSIFADDR (0x%lx)\n", cmd); - -#ifdef INET - if (ifa->ifa_addr->sa_family == AF_INET) { - if_setflagbits(ifp, IFF_UP, 0); - if (!(if_getdrvflags(ifp) & IFF_DRV_RUNNING)) { - QLNX_LOCK(ha); - qlnx_init_locked(ha); - QLNX_UNLOCK(ha); - } - QL_DPRINT4(ha, "SIOCSIFADDR (0x%lx) ipv4 [0x%08x]\n", - cmd, ntohl(IA_SIN(ifa)->sin_addr.s_addr)); - - arp_ifinit(ifp, ifa); - break; - } -#endif - ether_ioctl(ifp, cmd, data); - break; - case SIOCSIFMTU: QL_DPRINT4(ha, "SIOCSIFMTU (0x%lx)\n", cmd); @@ -2680,13 +2564,8 @@ qlnx_ioctl(if_t ifp, u_long cmd, caddr_t data) if (flags & IFF_UP) { if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { - if ((flags ^ ha->if_flags) & - IFF_PROMISC) { - ret = qlnx_set_promisc(ha, flags & IFF_PROMISC); - } else if ((if_getflags(ifp) ^ ha->if_flags) & - IFF_ALLMULTI) { - ret = qlnx_set_allmulti(ha, flags & IFF_ALLMULTI); - } + if (qlnx_set_promisc_allmulti(ha, flags) != 0) + ret = EINVAL; } else { ha->max_frame_size = if_getmtu(ifp) + ETHER_HDR_LEN + ETHER_CRC_LEN; @@ -2697,26 +2576,19 @@ qlnx_ioctl(if_t ifp, u_long cmd, caddr_t data) qlnx_stop(ha); } - ha->if_flags = if_getflags(ifp); QLNX_UNLOCK(ha); break; case SIOCADDMULTI: - QL_DPRINT4(ha, "%s (0x%lx)\n", "SIOCADDMULTI", cmd); - - if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { - if (qlnx_set_multi(ha, 1)) - ret = EINVAL; - } - break; - case SIOCDELMULTI: - QL_DPRINT4(ha, "%s (0x%lx)\n", "SIOCDELMULTI", cmd); + QL_DPRINT4(ha, "%s (0x%lx)\n", "SIOCADDMULTI/SIOCDELMULTI", cmd); - if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) { - if (qlnx_set_multi(ha, 0)) + QLNX_LOCK(ha); + if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) { + if (qlnx_set_multi(ha) != 0) ret = EINVAL; } + QLNX_UNLOCK(ha); break; case SIOCSIFMEDIA: @@ -3018,6 +2890,7 @@ qlnx_transmit_locked(if_t ifp, struct qlnx_fastpath *fp, struct mbuf *mp) drbr_advance(ifp, fp->tx_br); fp->tx_pkts_transmitted++; fp->tx_pkts_processed++; + ETHER_BPF_MTAP(ifp, mp); } mp = drbr_peek(ifp, fp->tx_br); @@ -3774,7 +3647,7 @@ qlnx_get_ifq_snd_maxlen(qlnx_host_t *ha) return(TX_RING_SIZE - 1); } -uint8_t * +static void qlnx_get_mac_addr(qlnx_host_t *ha) { struct ecore_hwfn *p_hwfn; @@ -3783,8 +3656,10 @@ qlnx_get_mac_addr(qlnx_host_t *ha) p_hwfn = &ha->cdev.hwfns[0]; - if (qlnx_vf_device(ha) != 0) - return (p_hwfn->hw_info.hw_mac_addr); + if (qlnx_vf_device(ha) != 0) { + memcpy(ha->primary_mac, p_hwfn->hw_info.hw_mac_addr, ETH_ALEN); + return; + } ecore_vf_read_bulletin(p_hwfn, &p_is_forced); if (ecore_vf_bulletin_get_forced_mac(p_hwfn, mac, &p_is_forced) == @@ -3794,8 +3669,6 @@ qlnx_get_mac_addr(qlnx_host_t *ha) p_is_forced, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); memcpy(ha->primary_mac, mac, ETH_ALEN); } - - return (ha->primary_mac); } static uint32_t @@ -6979,31 +6852,18 @@ qlnx_remove_all_ucast_mac(qlnx_host_t *ha) static int qlnx_remove_all_mcast_mac(qlnx_host_t *ha) { - struct ecore_filter_mcast *mcast; + struct ecore_filter_mcast mcast; struct ecore_dev *cdev; - int rc, i; + int rc; cdev = &ha->cdev; - mcast = &ha->ecore_mcast; - bzero(mcast, sizeof(struct ecore_filter_mcast)); - - mcast->opcode = ECORE_FILTER_REMOVE; + bzero(&mcast, sizeof(struct ecore_filter_mcast)); + mcast.opcode = ECORE_FILTER_FLUSH; - for (i = 0; i < QLNX_MAX_NUM_MULTICAST_ADDRS; i++) { - if (ha->mcast[i].addr[0] || ha->mcast[i].addr[1] || - ha->mcast[i].addr[2] || ha->mcast[i].addr[3] || - ha->mcast[i].addr[4] || ha->mcast[i].addr[5]) { - memcpy(&mcast->mac[i][0], &ha->mcast[i].addr[0], ETH_ALEN); - mcast->num_mc_addrs++; - } - } - mcast = &ha->ecore_mcast; - - rc = ecore_filter_mcast_cmd(cdev, mcast, ECORE_SPQ_MODE_CB, NULL); - - bzero(ha->mcast, (sizeof(qlnx_mcast_t) * QLNX_MAX_NUM_MULTICAST_ADDRS)); - ha->nmcast = 0; + rc = ecore_filter_mcast_cmd(cdev, &mcast, ECORE_SPQ_MODE_CB, NULL); + if (rc == 0) + bzero(ha->ecore_mcast_bins, sizeof(ha->ecore_mcast_bins)); return (rc); } @@ -7013,6 +6873,9 @@ qlnx_clean_filters(qlnx_host_t *ha) { int rc = 0; + /* Reset rx filter */ + ha->filter = 0; + /* Remove all unicast macs */ rc = qlnx_remove_all_ucast_mac(ha); if (rc) @@ -7056,40 +6919,20 @@ static int qlnx_set_rx_mode(qlnx_host_t *ha) { int rc = 0; - uint8_t filter; const if_t ifp = ha->ifp; - const struct ifaddr *ifa; - struct sockaddr_dl *sdl; - ifa = if_getifaddr(ifp); - if (if_gettype(ifp) == IFT_ETHER && ifa != NULL && - ifa->ifa_addr != NULL) { - sdl = (struct sockaddr_dl *) ifa->ifa_addr; - - rc = qlnx_set_ucast_rx_mac(ha, ECORE_FILTER_REPLACE, LLADDR(sdl)); - } else { - rc = qlnx_set_ucast_rx_mac(ha, ECORE_FILTER_REPLACE, ha->primary_mac); - } - if (rc) - return rc; + rc = qlnx_set_ucast_rx_mac(ha, ECORE_FILTER_REPLACE, if_getlladdr(ifp)); + if (rc) + return rc; - rc = qlnx_remove_all_mcast_mac(ha); + rc = qlnx_set_multi(ha); if (rc) return rc; - filter = ECORE_ACCEPT_UCAST_MATCHED | - ECORE_ACCEPT_MCAST_MATCHED | - ECORE_ACCEPT_BCAST; - - if (qlnx_vf_device(ha) == 0 || (if_getflags(ha->ifp) & IFF_PROMISC)) { - filter |= ECORE_ACCEPT_UCAST_UNMATCHED; - filter |= ECORE_ACCEPT_MCAST_UNMATCHED; - } else if (if_getflags(ha->ifp) & IFF_ALLMULTI) { - filter |= ECORE_ACCEPT_MCAST_UNMATCHED; - } - ha->filter = filter; - - rc = qlnx_set_rx_accept_filter(ha, filter); + if (qlnx_vf_device(ha) == 0) + rc = _qlnx_set_promisc_allmulti(ha, true, true); + else + rc = qlnx_set_promisc_allmulti(ha, if_getflags(ifp)); return (rc); } diff --git a/sys/dev/qlxgb/qla_os.c b/sys/dev/qlxgb/qla_os.c index 87e504a83c79..440490dc17a1 100644 --- a/sys/dev/qlxgb/qla_os.c +++ b/sys/dev/qlxgb/qla_os.c @@ -93,7 +93,7 @@ static device_method_t qla_pci_methods[] = { DEVMETHOD(device_probe, qla_pci_probe), DEVMETHOD(device_attach, qla_pci_attach), DEVMETHOD(device_detach, qla_pci_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t qla_pci_driver = { diff --git a/sys/dev/qlxgbe/ql_os.c b/sys/dev/qlxgbe/ql_os.c index a12f1efec082..7cf6e3296d25 100644 --- a/sys/dev/qlxgbe/ql_os.c +++ b/sys/dev/qlxgbe/ql_os.c @@ -106,7 +106,7 @@ static device_method_t qla_pci_methods[] = { DEVMETHOD(device_probe, qla_pci_probe), DEVMETHOD(device_attach, qla_pci_attach), DEVMETHOD(device_detach, qla_pci_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t qla_pci_driver = { diff --git a/sys/dev/qlxge/qls_os.c b/sys/dev/qlxge/qls_os.c index eca7006850e0..9173037457c2 100644 --- a/sys/dev/qlxge/qls_os.c +++ b/sys/dev/qlxge/qls_os.c @@ -99,7 +99,7 @@ static device_method_t qla_pci_methods[] = { DEVMETHOD(device_probe, qls_pci_probe), DEVMETHOD(device_attach, qls_pci_attach), DEVMETHOD(device_detach, qls_pci_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t qla_pci_driver = { diff --git a/sys/dev/quicc/quicc_bus.h b/sys/dev/quicc/quicc_bus.h index 01d8952dddbb..4c8bcd4210d4 100644 --- a/sys/dev/quicc/quicc_bus.h +++ b/sys/dev/quicc/quicc_bus.h @@ -29,9 +29,11 @@ #ifndef _DEV_QUICC_BUS_H_ #define _DEV_QUICC_BUS_H_ -#define QUICC_IVAR_CLOCK 1 /* The CPM clock. */ -#define QUICC_IVAR_BRGCLK 2 /* The BRG clock affected by SCCR. */ -#define QUICC_IVAR_DEVTYPE 3 +enum { + QUICC_IVAR_CLOCK = BUS_IVARS_PRIVATE, /* The CPM clock. */ + QUICC_IVAR_BRGCLK, /* The BRG clock affected by SCCR. */ + QUICC_IVAR_DEVTYPE +}; /* Device types. */ #define QUICC_DEVTYPE_SCC 1 diff --git a/sys/dev/random/armv8rng.c b/sys/dev/random/armv8rng.c index 9573c09aa77a..7aa6f4b0ded1 100644 --- a/sys/dev/random/armv8rng.c +++ b/sys/dev/random/armv8rng.c @@ -98,8 +98,8 @@ rndr_modevent(module_t mod, int type, void *unused) switch (type) { case MOD_LOAD: has_rndr = false; - if (get_kernel_reg(ID_AA64ISAR0_EL1, ®) && - ID_AA64ISAR0_RNDR_VAL(reg) != ID_AA64ISAR0_RNDR_NONE) { + get_kernel_reg(ID_AA64ISAR0_EL1, ®); + if (ID_AA64ISAR0_RNDR_VAL(reg) != ID_AA64ISAR0_RNDR_NONE) { has_rndr = true; random_source_register(&random_armv8_rndr); printf("random: fast provider: \"%s\"\n", diff --git a/sys/dev/regulator/regulator_fixed.c b/sys/dev/regulator/regulator_fixed.c index 55cdb5e4aeae..148bd28cdd16 100644 --- a/sys/dev/regulator/regulator_fixed.c +++ b/sys/dev/regulator/regulator_fixed.c @@ -380,6 +380,7 @@ regfix_parse_fdt(struct regfix_softc * sc) { phandle_t node; int rv; + char *name; struct regnode_init_def *init_def; node = ofw_bus_get_node(sc->dev); @@ -405,15 +406,21 @@ regfix_parse_fdt(struct regfix_softc * sc) if (OF_hasprop(node, "gpio-open-drain")) sc->init_def.gpio_open_drain = true; - if (!OF_hasprop(node, "gpio")) - return (0); - rv = ofw_bus_parse_xref_list_alloc(node, "gpio", "#gpio-cells", 0, - &sc->gpio_prodxref, &sc->gpio_ncells, &sc->gpio_cells); + if (OF_hasprop(node, "gpio")) + name = "gpio"; + else if (OF_hasprop(node, "gpios")) + name = "gpios"; + else + return(0); + + rv = ofw_bus_parse_xref_list_alloc(node, name, "#gpio-cells", + 0, &sc->gpio_prodxref, &sc->gpio_ncells, &sc->gpio_cells); if (rv != 0) { sc->gpio_prodxref = 0; - device_printf(sc->dev, "Malformed gpio property\n"); + device_printf(sc->dev, "Malformed gpios property\n"); return (ENXIO); } + return (0); } diff --git a/sys/dev/rge/if_rge.c b/sys/dev/rge/if_rge.c index fde8e9df31fe..8887e8d39ae4 100644 --- a/sys/dev/rge/if_rge.c +++ b/sys/dev/rge/if_rge.c @@ -67,6 +67,9 @@ #include "if_rge_sysctl.h" #include "if_rge_stats.h" +#define ETHER_IS_VALID(addr) \ + (!ETHER_IS_MULTICAST(addr.octet) && !ETHER_IS_ZERO(addr.octet)) + #define RGE_CSUM_FEATURES (CSUM_IP | CSUM_TCP | CSUM_UDP) static int rge_attach(device_t); @@ -100,12 +103,7 @@ static void rge_tx_task(void *, int); static void rge_txq_flush_mbufs(struct rge_softc *sc); static void rge_tick(void *); static void rge_link_state(struct rge_softc *); -#if 0 -#ifndef SMALL_KERNEL -int rge_wol(struct ifnet *, int); -void rge_wol_power(struct rge_softc *); -#endif -#endif +static void rge_setwol(struct rge_softc *); struct rge_matchid { uint16_t vendor; @@ -158,7 +156,11 @@ rge_attach_if(struct rge_softc *sc, const char *eaddr) if_setcapabilities(sc->sc_ifp, IFCAP_HWCSUM); if_setcapenable(sc->sc_ifp, if_getcapabilities(sc->sc_ifp)); - /* TODO: set WOL */ + /* Enable WOL if PM is supported. */ + if (pci_has_pm(sc->sc_dev)) { + if_setcapabilitiesbit(sc->sc_ifp, IFCAP_WOL_MAGIC, 0); + if_setcapenablebit(sc->sc_ifp, IFCAP_WOL_MAGIC, 0); + } /* Attach interface */ ether_ifattach(sc->sc_ifp, eaddr); @@ -182,7 +184,7 @@ rge_attach_if(struct rge_softc *sc, const char *eaddr) static int rge_attach(device_t dev) { - uint8_t eaddr[ETHER_ADDR_LEN]; + struct ether_addr eaddr; struct rge_softc *sc; struct rge_queues *q; uint32_t hwrev, reg; @@ -196,6 +198,8 @@ rge_attach(device_t dev) mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF); + callout_init_mtx(&sc->sc_timeout, &sc->sc_mtx, 0); + /* Enable bus mastering */ pci_enable_busmaster(dev); @@ -408,27 +412,31 @@ rge_attach(device_t dev) switch (hwrev) { case 0x60900000: sc->rge_type = MAC_R25; -// device_printf(dev, "RTL8125\n"); + device_printf(dev, "chip rev: RTL8125 (0x%08x)\n", hwrev); break; case 0x64100000: sc->rge_type = MAC_R25B; -// device_printf(dev, "RTL8125B\n"); + device_printf(dev, "chip rev: RTL8125B (0x%08x)\n", hwrev); break; case 0x64900000: sc->rge_type = MAC_R26_1; -// device_printf(dev, "RTL8126_1\n"); + device_printf(dev, "chip rev: RTL8126_1 (0x%08x)\n", hwrev); break; case 0x64a00000: sc->rge_type = MAC_R26_2; -// device_printf(dev, "RTL8126_2\n"); + device_printf(dev, "chip rev: RTL8126_2 (0x%08x)\n", hwrev); break; case 0x68800000: - sc->rge_type = MAC_R25D; -// device_printf(dev, "RTL8125D\n"); + sc->rge_type = MAC_R25D_1; + device_printf(dev, "chip rev: RTL8125D_1 (0x%08x)\n", hwrev); + break; + case 0x68900000: + sc->rge_type = MAC_R25D_2; + device_printf(dev, "chip rev: RTL8125D_2 (0x%08x)\n", hwrev); break; case 0x6c900000: sc->rge_type = MAC_R27; -// device_printf(dev, "RTL8127\n"); + device_printf(dev, "chip rev: RTL8127 (0x%08x)\n", hwrev); break; default: RGE_PRINT_ERROR(sc, "unknown version 0x%08x\n", hwrev); @@ -437,23 +445,19 @@ rge_attach(device_t dev) rge_config_imtype(sc, RGE_IMTYPE_SIM); - /* TODO: disable ASPM/ECPM? */ - -#if 0 - /* - * PCI Express check. - */ - if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIEXPRESS, - &offset, NULL)) { - /* Disable PCIe ASPM and ECPM. */ - reg = pci_conf_read(pa->pa_pc, pa->pa_tag, - offset + PCI_PCIE_LCSR); - reg &= ~(PCI_PCIE_LCSR_ASPM_L0S | PCI_PCIE_LCSR_ASPM_L1 | - PCI_PCIE_LCSR_ECPM); - pci_conf_write(pa->pa_pc, pa->pa_tag, offset + PCI_PCIE_LCSR, - reg); + /* Disable PCIe ASPM and ECPM if requested. */ + if (sc->sc_disable_aspm) { + int ecap; + if (pci_find_cap(dev, PCIY_EXPRESS, &ecap) == 0) { + uint16_t lctl; + lctl = pci_read_config(dev, + ecap + PCIER_LINK_CTL, 2); + lctl &= ~(PCIEM_LINK_CTL_ASPMC | + PCIEM_LINK_CTL_ECPM); + pci_write_config(dev, + ecap + PCIER_LINK_CTL, lctl, 2); + } } -#endif RGE_LOCK(sc); if (rge_chipinit(sc)) { @@ -461,9 +465,15 @@ rge_attach(device_t dev) goto fail; } - rge_get_macaddr(sc, eaddr); + rge_get_macaddr(sc, eaddr.octet); RGE_UNLOCK(sc); + if (!ETHER_IS_VALID(eaddr)) { + device_printf(dev, + "No MAC address found. Using ether_gen_addr().\n"); + ether_gen_addr_byname(device_get_nameunit(dev), &eaddr); + } + if (rge_allocmem(sc)) goto fail; if (rge_alloc_stats_mem(sc)) @@ -477,7 +487,7 @@ rge_attach(device_t dev) ifmedia_set(&sc->sc_media, IFM_ETHER | IFM_AUTO); sc->sc_media.ifm_media = sc->sc_media.ifm_cur->ifm_media; - rge_attach_if(sc, eaddr); + rge_attach_if(sc, eaddr.octet); /* * TODO: technically should be per txq but we only support @@ -497,8 +507,6 @@ rge_attach(device_t dev) TASK_INIT(&sc->sc_tx_task, 0, rge_tx_task, sc); - callout_init_mtx(&sc->sc_timeout, &sc->sc_mtx, 0); - return (0); fail: rge_detach(dev); @@ -641,26 +649,6 @@ rge_detach(device_t dev) return (0); } -#if 0 - -int -rge_activate(struct device *self, int act) -{ -#ifndef SMALL_KERNEL - struct rge_softc *sc = (struct rge_softc *)self; -#endif - - switch (act) { - case DVACT_POWERDOWN: -#ifndef SMALL_KERNEL - rge_wol_power(sc); -#endif - break; - } - return (0); -} -#endif - static void rge_intr_msi(void *arg) { @@ -946,29 +934,24 @@ rge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) case SIOCSIFFLAGS: RGE_LOCK(sc); if ((if_getflags(ifp) & IFF_UP) != 0) { - if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) { - /* - * TODO: handle promisc/iffmulti changing - * without reprogramming everything. - */ + if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) { + if (((if_getflags(ifp) ^ sc->rge_if_flags) + & (IFF_PROMISC | IFF_ALLMULTI)) != 0) + rge_iff_locked(sc); + } else rge_init_locked(sc); - } else { - /* Reinit promisc/multi just in case */ - rge_iff_locked(sc); - } } else { - if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) { + if ((if_getdrvflags(ifp) & IFF_DRV_RUNNING) != 0) rge_stop_locked(sc); - } } + sc->rge_if_flags = if_getflags(ifp); RGE_UNLOCK(sc); break; case SIOCADDMULTI: case SIOCDELMULTI: RGE_LOCK(sc); - if ((if_getflags(ifp) & IFF_DRV_RUNNING) != 0) { + if ((if_getflags(ifp) & IFF_DRV_RUNNING) != 0) rge_iff_locked(sc); - } RGE_UNLOCK(sc); break; case SIOCGIFMEDIA: @@ -1006,7 +989,9 @@ rge_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) reinit = 1; } - /* TODO: WOL */ + if ((mask & IFCAP_WOL_MAGIC) != 0 && + (if_getcapabilities(ifp) & IFCAP_WOL_MAGIC) != 0) + if_togglecapenable(ifp, IFCAP_WOL_MAGIC); if ((mask & IFCAP_RXCSUM) != 0 && (if_getcapabilities(ifp) & IFCAP_RXCSUM) != 0) { @@ -1112,7 +1097,7 @@ rge_init_locked(struct rge_softc *sc) * causing this to be initialised both from the ioctl * API and if_init() API. */ -// RGE_PRINT_ERROR(sc, "%s: called whilst running?\n", __func__); +/* RGE_PRINT_ERROR(sc, "%s: called whilst running?\n", __func__); */ return; } @@ -1159,7 +1144,7 @@ rge_init_locked(struct rge_softc *sc) rxconf = RGE_RXCFG_CONFIG; else if (sc->rge_type == MAC_R25B) rxconf = RGE_RXCFG_CONFIG_8125B; - else if (sc->rge_type == MAC_R25D) + else if (RGE_TYPE_R25D(sc)) rxconf = RGE_RXCFG_CONFIG_8125D; else rxconf = RGE_RXCFG_CONFIG_8126; @@ -1173,7 +1158,7 @@ rge_init_locked(struct rge_softc *sc) /* Disable L1 timeout. */ val = rge_read_csi(sc, 0x890) & ~0x00000001; rge_write_csi(sc, 0x890, val); - } else if (sc->rge_type != MAC_R25D) + } else if (!RGE_TYPE_R25D(sc)) RGE_WRITE_2(sc, 0x0382, 0x221b); RGE_WRITE_1(sc, RGE_RSS_CTRL, 0); @@ -1199,7 +1184,7 @@ rge_init_locked(struct rge_softc *sc) val = rge_read_mac_ocp(sc, 0xe614); val &= (sc->rge_type == MAC_R27) ? ~0x0f00 : ~0x0700; - if (sc->rge_type == MAC_R25 || sc->rge_type == MAC_R25D) + if (sc->rge_type == MAC_R25 || RGE_TYPE_R25D(sc)) rge_write_mac_ocp(sc, 0xe614, val | 0x0300); else if (sc->rge_type == MAC_R25B) rge_write_mac_ocp(sc, 0xe614, val | 0x0200); @@ -1235,7 +1220,7 @@ rge_init_locked(struct rge_softc *sc) val = rge_read_mac_ocp(sc, 0xea1c) & ~0x0003; rge_write_mac_ocp(sc, 0xea1c, val | 0x0001); - if (sc->rge_type == MAC_R25D) + if (RGE_TYPE_R25D(sc)) rge_write_mac_ocp(sc, 0xe0c0, 0x4403); else rge_write_mac_ocp(sc, 0xe0c0, 0x4000); @@ -1251,7 +1236,7 @@ rge_init_locked(struct rge_softc *sc) if (sc->rge_type == MAC_R25) RGE_SETBIT_1(sc, RGE_MCUCMD, 0x01); - if (sc->rge_type != MAC_R25D) { + if (!RGE_TYPE_R25D(sc)) { /* Disable EEE plus. */ RGE_MAC_CLRBIT(sc, 0xe080, 0x0002); } @@ -1306,7 +1291,7 @@ rge_init_locked(struct rge_softc *sc) val = rge_read_csi(sc, 0x98) & ~0x0000ff00; rge_write_csi(sc, 0x98, val); - if (sc->rge_type == MAC_R25D) { + if (RGE_TYPE_R25D(sc)) { val = rge_read_mac_ocp(sc, 0xe092) & ~0x00ff; rge_write_mac_ocp(sc, 0xe092, val | 0x0008); } else @@ -1749,13 +1734,6 @@ rge_freemem(struct rge_softc *sc) RGE_ASSERT_UNLOCKED(sc); - /* TX desc */ - bus_dmamap_unload(sc->sc_dmat_tx_desc, q->q_tx.rge_tx_list_map); - if (q->q_tx.rge_tx_list != NULL) - bus_dmamem_free(sc->sc_dmat_tx_desc, q->q_tx.rge_tx_list, - q->q_tx.rge_tx_list_map); - memset(&q->q_tx, 0, sizeof(q->q_tx)); - /* TX buf */ for (i = 0; i < RGE_TX_LIST_CNT; i++) { struct rge_txq *tx = &q->q_tx.rge_txq[i]; @@ -1787,12 +1765,13 @@ rge_freemem(struct rge_softc *sc) } } - /* RX desc */ - bus_dmamap_unload(sc->sc_dmat_rx_desc, q->q_rx.rge_rx_list_map); - if (q->q_rx.rge_rx_list != 0) - bus_dmamem_free(sc->sc_dmat_rx_desc, q->q_rx.rge_rx_list, - q->q_rx.rge_rx_list_map); - memset(&q->q_rx, 0, sizeof(q->q_tx)); + /* TX desc */ + if (q->q_tx.rge_tx_list != NULL) { + bus_dmamap_unload(sc->sc_dmat_tx_desc, q->q_tx.rge_tx_list_map); + bus_dmamem_free(sc->sc_dmat_tx_desc, q->q_tx.rge_tx_list, + q->q_tx.rge_tx_list_map); + } + memset(&q->q_tx, 0, sizeof(q->q_tx)); /* RX buf */ for (i = 0; i < RGE_RX_LIST_CNT; i++) { @@ -1817,6 +1796,14 @@ rge_freemem(struct rge_softc *sc) } } + /* RX desc */ + if (q->q_rx.rge_rx_list != NULL) { + bus_dmamap_unload(sc->sc_dmat_rx_desc, q->q_rx.rge_rx_list_map); + bus_dmamem_free(sc->sc_dmat_rx_desc, q->q_rx.rge_rx_list, + q->q_rx.rge_rx_list_map); + } + memset(&q->q_rx, 0, sizeof(q->q_tx)); + return (0); } @@ -1832,9 +1819,10 @@ rge_free_stats_mem(struct rge_softc *sc) RGE_ASSERT_UNLOCKED(sc); - bus_dmamap_unload(sc->sc_dmat_stats_buf, ss->map); - if (ss->stats != NULL) + if (ss->stats != NULL) { + bus_dmamap_unload(sc->sc_dmat_stats_buf, ss->map); bus_dmamem_free(sc->sc_dmat_stats_buf, ss->stats, ss->map); + } memset(ss, 0, sizeof(*ss)); return (0); } @@ -2088,9 +2076,10 @@ rge_rxeof(struct rge_queues *q, struct mbufq *mq) uint32_t rxstat, extsts; int i, mlen, rx = 0; int cons, prod; - int maxpkt = 16; /* XXX TODO: make this a tunable */ + int maxpkt; bool check_hwcsum; + maxpkt = sc->sc_rx_process_limit; check_hwcsum = ((if_getcapenable(sc->sc_ifp) & IFCAP_RXCSUM) != 0); RGE_ASSERT_LOCKED(sc); @@ -2393,7 +2382,7 @@ rge_hash_maddr(void *arg, struct sockaddr_dl *sdl, u_int cnt) { uint32_t crc, *hashes = arg; - // XXX TODO: validate this does addrlo? */ + /* XXX TODO: validate this does addrlo? */ crc = ether_crc32_be(LLADDR(sdl), ETHER_ADDR_LEN) >> 26; crc &= 0x3f; @@ -2608,6 +2597,22 @@ rge_link_state(struct rge_softc *sc) } } +static void +rge_setwol(struct rge_softc *sc) +{ + if_t ifp = sc->sc_ifp; + int enable; + + mtx_assert(&sc->sc_mtx, MA_OWNED); + + if (!pci_has_pm(sc->sc_dev)) + return; + + enable = (if_getcapenable(ifp) & IFCAP_WOL_MAGIC) != 0; + + rge_wol_config(sc, enable); +} + /** * @brief Suspend */ @@ -2618,7 +2623,7 @@ rge_suspend(device_t dev) RGE_LOCK(sc); rge_stop_locked(sc); - /* TODO: wake on lan */ + rge_setwol(sc); sc->sc_suspended = true; RGE_UNLOCK(sc); @@ -2634,7 +2639,6 @@ rge_resume(device_t dev) struct rge_softc *sc = device_get_softc(dev); RGE_LOCK(sc); - /* TODO: wake on lan */ /* reinit if required */ if (if_getflags(sc->sc_ifp) & IFF_UP) @@ -2657,6 +2661,7 @@ rge_shutdown(device_t dev) RGE_LOCK(sc); rge_stop_locked(sc); + rge_setwol(sc); RGE_UNLOCK(sc); return (0); diff --git a/sys/dev/rge/if_rge_hw.c b/sys/dev/rge/if_rge_hw.c index ccd6580b2cfc..ba01e389af14 100644 --- a/sys/dev/rge/if_rge_hw.c +++ b/sys/dev/rge/if_rge_hw.c @@ -78,7 +78,8 @@ static void rge_phy_config_mac_r26_1(struct rge_softc *sc); static void rge_phy_config_mac_r26_2(struct rge_softc *sc); static void rge_phy_config_mac_r25(struct rge_softc *sc); static void rge_phy_config_mac_r25b(struct rge_softc *sc); -static void rge_phy_config_mac_r25d(struct rge_softc *sc); +static void rge_phy_config_mac_r25d_1(struct rge_softc *); +static void rge_phy_config_mac_r25d_2(struct rge_softc *); static void rge_phy_config_mcu(struct rge_softc *sc, uint16_t rcodever); static void rge_hw_init(struct rge_softc *sc); static void rge_disable_phy_ocp_pwrsave(struct rge_softc *sc); @@ -230,7 +231,7 @@ rge_mac_config_mcu(struct rge_softc *sc, enum rge_mac_type type) rge_write_mac_ocp(sc, rtl8125b_mac_bps[i].reg, rtl8125b_mac_bps[i].val); } - } else if (type == MAC_R25D) { + } else if (type == MAC_R25D_1) { for (npages = 0; npages < 3; npages++) { rge_switch_mcu_ram_page(sc, npages); @@ -268,6 +269,35 @@ rge_mac_config_mcu(struct rge_softc *sc, enum rge_mac_type type) rge_write_mac_ocp(sc, 0xfc26, 0x8000); rge_write_mac_ocp(sc, 0xfc28, 0x14a2); rge_write_mac_ocp(sc, 0xfc48, 0x0001); + } else if (type == MAC_R25D_2) { + for (npages = 0; npages < 3; npages++) { + rge_switch_mcu_ram_page(sc, npages); + + for (i = 0; i < nitems(rtl8125d_2_mac_bps); i++) { + if (npages == 0) + rge_write_mac_ocp(sc, + rtl8125d_2_mac_bps[i].reg, + rtl8125d_2_mac_bps[i].val); + else + rge_write_mac_ocp(sc, + rtl8125d_2_mac_bps[i].reg, 0); + } + + for (reg = 0xf884; reg <= 0xf9f6; reg += 2) + rge_write_mac_ocp(sc, reg, 0); + + rge_write_mac_ocp(sc, 0xf9f8, + (npages == 2) ? 0x6938 : 0); + rge_write_mac_ocp(sc, 0xf9fa, + (npages == 2) ? 0x0a19: 0); + rge_write_mac_ocp(sc, 0xf9fc, + (npages == 2) ? 0x030e: 0); + rge_write_mac_ocp(sc, 0xf9fe, + (npages == 2) ? 0x0b2f: 0); + } + rge_write_mac_ocp(sc, 0xfc26, 0x8000); + rge_write_mac_ocp(sc, 0xfc28, 0x2382); + rge_write_mac_ocp(sc, 0xfc48, 0x0001); } } @@ -300,7 +330,7 @@ rge_mac_config_ext_mcu(struct rge_softc *sc, enum rge_mac_type type) } rge_write_mac_ocp(sc, 0xfc26, 0x8000); rge_write_mac_ocp(sc, 0xfc2c, 0x2360); - rge_write_mac_ocp(sc, 0xfc2E, 0x14a4); + rge_write_mac_ocp(sc, 0xfc2e, 0x14a4); rge_write_mac_ocp(sc, 0xfc30, 0x415e); rge_write_mac_ocp(sc, 0xfc32, 0x41e4); rge_write_mac_ocp(sc, 0xfc34, 0x4280); @@ -508,8 +538,11 @@ rge_phy_config(struct rge_softc *sc) case MAC_R25B: rge_phy_config_mac_r25b(sc); break; - case MAC_R25D: - rge_phy_config_mac_r25d(sc); + case MAC_R25D_1: + rge_phy_config_mac_r25d_1(sc); + break; + case MAC_R25D_2: + rge_phy_config_mac_r25d_2(sc); break; case MAC_R26_1: rge_phy_config_mac_r26_1(sc); @@ -531,7 +564,7 @@ rge_phy_config(struct rge_softc *sc) if (sc->rge_type == MAC_R25) { RGE_MAC_CLRBIT(sc, 0xeb62, 0x0006); RGE_PHY_CLRBIT(sc, 0xa432, 0x0010); - } else if (sc->rge_type == MAC_R25B || sc->rge_type == MAC_R25D) + } else if (sc->rge_type == MAC_R25B || RGE_TYPE_R25D(sc)) RGE_PHY_SETBIT(sc, 0xa432, 0x0010); RGE_PHY_CLRBIT(sc, 0xa5d0, (sc->rge_type == MAC_R27) ? 0x000e : 0x0006); @@ -1363,12 +1396,12 @@ rge_phy_config_mac_r25b(struct rge_softc *sc) } static void -rge_phy_config_mac_r25d(struct rge_softc *sc) +rge_phy_config_mac_r25d_1(struct rge_softc *sc) { uint16_t val; int i; - rge_phy_config_mcu(sc, RGE_MAC_R25D_RCODE_VER); + rge_phy_config_mcu(sc, RGE_MAC_R25D_1_RCODE_VER); RGE_PHY_SETBIT(sc, 0xa442, 0x0800); @@ -1556,6 +1589,67 @@ rge_phy_config_mac_r25d(struct rge_softc *sc) } static void +rge_phy_config_mac_r25d_2(struct rge_softc *sc) +{ + uint16_t val; + + rge_phy_config_mcu(sc, RGE_MAC_R25D_2_RCODE_VER); + + RGE_PHY_SETBIT(sc, 0xa442, 0x0800); + + rge_patch_phy_mcu(sc, 1); + val = rge_read_phy_ocp(sc, 0xbcd8) & ~0xc000; + rge_write_phy_ocp(sc, 0xbcd8, val | 0x4000); + RGE_PHY_SETBIT(sc, 0xbcd8, 0xc000); + val = rge_read_phy_ocp(sc, 0xbcd8) & ~0xc000; + rge_write_phy_ocp(sc, 0xbcd8, val | 0x4000); + val = rge_read_phy_ocp(sc, 0xbc80) & ~0x001f; + rge_write_phy_ocp(sc, 0xbc80, val | 0x0004); + RGE_PHY_SETBIT(sc, 0xbc82, 0xe000); + RGE_PHY_SETBIT(sc, 0xbc82, 0x1c00); + val = rge_read_phy_ocp(sc, 0xbc80) & ~0x001f; + rge_write_phy_ocp(sc, 0xbc80, val | 0x0005); + val = rge_read_phy_ocp(sc, 0xbc82) & ~0x00e0; + rge_write_phy_ocp(sc, 0xbc82, val | 0x0040); + RGE_PHY_SETBIT(sc, 0xbc82, 0x001c); + RGE_PHY_CLRBIT(sc, 0xbcd8, 0xc000); + val = rge_read_phy_ocp(sc, 0xbcd8) & ~0xc000; + rge_write_phy_ocp(sc, 0xbcd8, val | 0x8000); + RGE_PHY_CLRBIT(sc, 0xbcd8, 0xc000); + rge_patch_phy_mcu(sc, 0); + + val = rge_read_phy_ocp(sc, 0xac7e) & ~0x01fc; + rge_write_phy_ocp(sc, 0xac7e, val | 0x00b4); + rge_write_phy_ocp(sc, 0xb87c, 0x8105); + val = rge_read_phy_ocp(sc, 0xb87e) & ~0xff00; + rge_write_phy_ocp(sc, 0xb87e, val | 0x7a00); + rge_write_phy_ocp(sc, 0xb87c, 0x8117); + val = rge_read_phy_ocp(sc, 0xb87e) & ~0xff00; + rge_write_phy_ocp(sc, 0xb87e, val | 0x3a00); + rge_write_phy_ocp(sc, 0xb87c, 0x8103); + val = rge_read_phy_ocp(sc, 0xb87e) & ~0xff00; + rge_write_phy_ocp(sc, 0xb87e, val | 0x7400); + rge_write_phy_ocp(sc, 0xb87c, 0x8115); + val = rge_read_phy_ocp(sc, 0xb87e) & ~0xff00; + rge_write_phy_ocp(sc, 0xb87e, val | 0x3400); + rge_write_phy_ocp(sc, 0xb87c, 0x8feb); + val = rge_read_phy_ocp(sc, 0xb87e) & ~0xff00; + rge_write_phy_ocp(sc, 0xb87e, val | 0x0500); + rge_write_phy_ocp(sc, 0xb87c, 0x8fea); + val = rge_read_phy_ocp(sc, 0xb87e) & ~0xff00; + rge_write_phy_ocp(sc, 0xb87e, val | 0x0700); + rge_write_phy_ocp(sc, 0xb87c, 0x80d6); + val = rge_read_phy_ocp(sc, 0xb87e) & ~0xff00; + rge_write_phy_ocp(sc, 0xb87e, val | 0xef00); + RGE_PHY_CLRBIT(sc, 0xa5d4, 0x0020); + RGE_PHY_CLRBIT(sc, 0xa654, 0x0800); + RGE_PHY_CLRBIT(sc, 0xa448, 0x0400); + RGE_PHY_CLRBIT(sc, 0xa586, 0x0400); + RGE_PHY_SETBIT(sc, 0xa430, 0x1001); + RGE_PHY_SETBIT(sc, 0xa442, 0x0080); +} + +static void rge_phy_config_mcu(struct rge_softc *sc, uint16_t rcodever) { if (sc->rge_rcodever != rcodever) { @@ -1586,22 +1680,37 @@ rge_phy_config_mcu(struct rge_softc *sc, uint16_t rcodever) for (i = 0; i < nitems(mac_r25b_mcu); i++) rge_write_phy_ocp(sc, mac_r25b_mcu[i].reg, mac_r25b_mcu[i].val); - } else if (sc->rge_type == MAC_R25D) { + } else if (sc->rge_type == MAC_R25D_1) { for (i = 0; i < 2403; i++) rge_write_phy_ocp(sc, - mac_r25d_mcu[i].reg, mac_r25d_mcu[i].val); + mac_r25d_1_mcu[i].reg, + mac_r25d_1_mcu[i].val); rge_patch_phy_mcu(sc, 0); rge_patch_phy_mcu(sc, 1); for (; i < 2528; i++) rge_write_phy_ocp(sc, - mac_r25d_mcu[i].reg, mac_r25d_mcu[i].val); + mac_r25d_1_mcu[i].reg, + mac_r25d_1_mcu[i].val); rge_patch_phy_mcu(sc, 0); rge_patch_phy_mcu(sc, 1); - for (; i < nitems(mac_r25d_mcu); i++) + for (; i < nitems(mac_r25d_1_mcu); i++) + rge_write_phy_ocp(sc, + mac_r25d_1_mcu[i].reg, + mac_r25d_1_mcu[i].val); + } else if (sc->rge_type == MAC_R25D_2) { + for (i = 0; i < 1269; i++) rge_write_phy_ocp(sc, - mac_r25d_mcu[i].reg, mac_r25d_mcu[i].val); + mac_r25d_2_mcu[i].reg, + mac_r25d_2_mcu[i].val); + rge_patch_phy_mcu(sc, 0); + + rge_patch_phy_mcu(sc, 1); + for (; i < nitems(mac_r25d_2_mcu); i++) + rge_write_phy_ocp(sc, + mac_r25d_2_mcu[i].reg, + mac_r25d_2_mcu[i].val); } else if (sc->rge_type == MAC_R26_1) { for (i = 0; i < 6989; i++) rge_write_phy_ocp(sc, @@ -2087,50 +2196,37 @@ rge_get_link_status(struct rge_softc *sc) return ((RGE_READ_2(sc, RGE_PHYSTAT) & RGE_PHYSTAT_LINK) ? 1 : 0); } -#if 0 -#ifndef SMALL_KERNEL -int -rge_wol(struct ifnet *ifp, int enable) +void +rge_wol_config(struct rge_softc *sc, int enable) { - struct rge_softc *sc = ifp->if_softc; - - if (enable) { - if (!(RGE_READ_1(sc, RGE_CFG1) & RGE_CFG1_PM_EN)) { - printf("%s: power management is disabled, " - "cannot do WOL\n", sc->sc_dev.dv_xname); - return (ENOTSUP); - } - - } - - rge_iff(sc); - if (enable) RGE_MAC_SETBIT(sc, 0xc0b6, 0x0001); else RGE_MAC_CLRBIT(sc, 0xc0b6, 0x0001); + /* Enable config register write. */ RGE_SETBIT_1(sc, RGE_EECMD, RGE_EECMD_WRITECFG); - RGE_CLRBIT_1(sc, RGE_CFG5, RGE_CFG5_WOL_LANWAKE | RGE_CFG5_WOL_UCAST | - RGE_CFG5_WOL_MCAST | RGE_CFG5_WOL_BCAST); + + /* Clear all WOL bits, then set as requested. */ RGE_CLRBIT_1(sc, RGE_CFG3, RGE_CFG3_WOL_LINK | RGE_CFG3_WOL_MAGIC); - if (enable) + RGE_CLRBIT_1(sc, RGE_CFG5, RGE_CFG5_WOL_LANWAKE | + RGE_CFG5_WOL_UCAST | RGE_CFG5_WOL_MCAST | RGE_CFG5_WOL_BCAST); + if (enable) { + RGE_SETBIT_1(sc, RGE_CFG3, RGE_CFG3_WOL_MAGIC); RGE_SETBIT_1(sc, RGE_CFG5, RGE_CFG5_WOL_LANWAKE); - RGE_CLRBIT_1(sc, RGE_EECMD, RGE_EECMD_WRITECFG); + } - return (0); -} + /* Config register write done. */ + RGE_CLRBIT_1(sc, RGE_EECMD, RGE_EECMD_WRITECFG); -void -rge_wol_power(struct rge_softc *sc) -{ - /* Disable RXDV gate. */ - RGE_CLRBIT_1(sc, RGE_PPSW, 0x08); - DELAY(2000); + if (enable) { + /* Disable RXDV gate so WOL packets can reach the NIC. */ + RGE_CLRBIT_1(sc, RGE_PPSW, 0x08); + DELAY(2000); - RGE_SETBIT_1(sc, RGE_CFG1, RGE_CFG1_PM_EN); - RGE_SETBIT_1(sc, RGE_CFG2, RGE_CFG2_PMSTS_EN); + /* Enable power management. */ + RGE_SETBIT_1(sc, RGE_CFG1, RGE_CFG1_PM_EN); + RGE_SETBIT_1(sc, RGE_CFG2, RGE_CFG2_PMSTS_EN); + } } -#endif -#endif diff --git a/sys/dev/rge/if_rge_hw.h b/sys/dev/rge/if_rge_hw.h index 86f0da7c87b3..4e6ee5f1975f 100644 --- a/sys/dev/rge/if_rge_hw.h +++ b/sys/dev/rge/if_rge_hw.h @@ -37,5 +37,6 @@ extern uint16_t rge_read_phy(struct rge_softc *, uint16_t, uint16_t); extern void rge_write_phy_ocp(struct rge_softc *, uint16_t, uint16_t); extern uint16_t rge_read_phy_ocp(struct rge_softc *sc, uint16_t reg); extern int rge_get_link_status(struct rge_softc *); +extern void rge_wol_config(struct rge_softc *, int); #endif /* __IF_RGE_HW_H__ */ diff --git a/sys/dev/rge/if_rge_microcode.h b/sys/dev/rge/if_rge_microcode.h index f2803b869e3f..15f07099f80e 100644 --- a/sys/dev/rge/if_rge_microcode.h +++ b/sys/dev/rge/if_rge_microcode.h @@ -166,6 +166,31 @@ static const struct rge_hw_regaddr_array rtl8125b_mac_bps[] = { { 0xfc30, 0x4a20 }, { 0xfc32, 0x47a0 }, { 0xfc48, 0x003f } }; +static const struct rge_hw_regaddr_array rtl8125d_2_mac_bps[] = { + { 0xf800, 0xe010 }, { 0xf802, 0xe014 }, { 0xf804, 0xe016 }, + { 0xf806, 0xe018 }, { 0xf808, 0xe01a }, { 0xf80a, 0xe01c }, + { 0xf80c, 0xe01e }, { 0xf80e, 0xe020 }, { 0xf810, 0xe022 }, + { 0xf812, 0xe024 }, { 0xf814, 0xe026 }, { 0xf816, 0xe028 }, + { 0xf818, 0xe02a }, { 0xf81a, 0xe02c }, { 0xf81c, 0xe02e }, + { 0xf81e, 0xe030 }, { 0xf820, 0xc104 }, { 0xf822, 0xc202 }, + { 0xf824, 0xba00 }, { 0xf826, 0x2384 }, { 0xf828, 0xd116 }, + { 0xf82a, 0xc602 }, { 0xf82c, 0xbe00 }, { 0xf82e, 0x0000 }, + { 0xf830, 0xc602 }, { 0xf832, 0xbe00 }, { 0xf834, 0x0000 }, + { 0xf836, 0xc602 }, { 0xf838, 0xbe00 }, { 0xf83a, 0x0000 }, + { 0xf83c, 0xc602 }, { 0xf83e, 0xbe00 }, { 0xf840, 0x0000 }, + { 0xf842, 0xc602 }, { 0xf844, 0xbe00 }, { 0xf846, 0x0000 }, + { 0xf848, 0xc602 }, { 0xf84a, 0xbe00 }, { 0xf84c, 0x0000 }, + { 0xf84e, 0xc602 }, { 0xf850, 0xbe00 }, { 0xf852, 0x0000 }, + { 0xf854, 0xc602 }, { 0xf856, 0xbe00 }, { 0xf858, 0x0000 }, + { 0xf85a, 0xc602 }, { 0xf85c, 0xbe00 }, { 0xf85e, 0x0000 }, + { 0xf860, 0xc602 }, { 0xf862, 0xbe00 }, { 0xf864, 0x0000 }, + { 0xf866, 0xc602 }, { 0xf868, 0xbe00 }, { 0xf86a, 0x0000 }, + { 0xf86c, 0xc602 }, { 0xf86e, 0xbe00 }, { 0xf870, 0x0000 }, + { 0xf872, 0xc602 }, { 0xf874, 0xbe00 }, { 0xf876, 0x0000 }, + { 0xf878, 0xc602 }, { 0xf87a, 0xbe00 }, { 0xf87c, 0x0000 }, + { 0xf87e, 0xc602 }, { 0xf880, 0xbe00 }, { 0xf882, 0x0000 } +}; + struct rge_mac_bps { int count; const uint16_t *regs; @@ -489,6 +514,615 @@ static const struct rge_hw_regaddr_array mac_r27_ephy[] = { { 0x941c, 0x0190 }, { 0x981c, 0x0140 }, { 0x9c1c, 0x0140 } }; +static const struct rge_hw_regaddr_array mac_r25d_2_mcu[] = { + { 0xa436, 0x8023 }, { 0xa438, 0x3801 }, { 0xa436, 0xb82e }, + { 0xa438, 0x0001 }, { 0xb820, 0x0090 }, { 0xa436, 0xa016 }, + { 0xa438, 0x0000 }, { 0xa436, 0xa012 }, { 0xa438, 0x0000 }, + { 0xa436, 0xa014 }, { 0xa438, 0x1800 }, { 0xa438, 0x8010 }, + { 0xa438, 0x1800 }, { 0xa438, 0x808e }, { 0xa438, 0x1800 }, + { 0xa438, 0x80d6 }, { 0xa438, 0x1800 }, { 0xa438, 0x81e2 }, + { 0xa438, 0x1800 }, { 0xa438, 0x81e2 }, { 0xa438, 0x1800 }, + { 0xa438, 0x81e2 }, { 0xa438, 0x1800 }, { 0xa438, 0x81e2 }, + { 0xa438, 0x1800 }, { 0xa438, 0x81e2 }, { 0xa438, 0xd500 }, + { 0xa438, 0xc48d }, { 0xa438, 0xd504 }, { 0xa438, 0x8d03 }, + { 0xa438, 0xd701 }, { 0xa438, 0x4045 }, { 0xa438, 0xad02 }, + { 0xa438, 0xd504 }, { 0xa438, 0xd706 }, { 0xa438, 0x2529 }, + { 0xa438, 0x8021 }, { 0xa438, 0xd718 }, { 0xa438, 0x607b }, + { 0xa438, 0x40da }, { 0xa438, 0xf019 }, { 0xa438, 0x459a }, + { 0xa438, 0xf03f }, { 0xa438, 0xd718 }, { 0xa438, 0x62bb }, + { 0xa438, 0xbb01 }, { 0xa438, 0xd75e }, { 0xa438, 0x6231 }, + { 0xa438, 0x0cf0 }, { 0xa438, 0x0c10 }, { 0xa438, 0xd501 }, + { 0xa438, 0xce01 }, { 0xa438, 0xd70c }, { 0xa438, 0x6147 }, + { 0xa438, 0x8480 }, { 0xa438, 0x8440 }, { 0xa438, 0x8420 }, + { 0xa438, 0xa410 }, { 0xa438, 0xce00 }, { 0xa438, 0xd505 }, + { 0xa438, 0x0c0f }, { 0xa438, 0x0808 }, { 0xa438, 0xf002 }, + { 0xa438, 0xa4f0 }, { 0xa438, 0xf03c }, { 0xa438, 0xbb02 }, + { 0xa438, 0xd75e }, { 0xa438, 0x6231 }, { 0xa438, 0x0cf0 }, + { 0xa438, 0x0c20 }, { 0xa438, 0xd501 }, { 0xa438, 0xce01 }, + { 0xa438, 0xd70c }, { 0xa438, 0x6147 }, { 0xa438, 0x8480 }, + { 0xa438, 0x8440 }, { 0xa438, 0xa420 }, { 0xa438, 0x8410 }, + { 0xa438, 0xce00 }, { 0xa438, 0xd505 }, { 0xa438, 0x0c0f }, + { 0xa438, 0x0804 }, { 0xa438, 0xf002 }, { 0xa438, 0xa4f0 }, + { 0xa438, 0xf028 }, { 0xa438, 0xbb04 }, { 0xa438, 0xd75e }, + { 0xa438, 0x6231 }, { 0xa438, 0x0cf0 }, { 0xa438, 0x0c40 }, + { 0xa438, 0xd501 }, { 0xa438, 0xce01 }, { 0xa438, 0xd70c }, + { 0xa438, 0x6147 }, { 0xa438, 0x8480 }, { 0xa438, 0xa440 }, + { 0xa438, 0x8420 }, { 0xa438, 0x8410 }, { 0xa438, 0xce00 }, + { 0xa438, 0xd505 }, { 0xa438, 0x0c0f }, { 0xa438, 0x0802 }, + { 0xa438, 0xf002 }, { 0xa438, 0xa4f0 }, { 0xa438, 0xf014 }, + { 0xa438, 0xbb08 }, { 0xa438, 0xd75e }, { 0xa438, 0x6231 }, + { 0xa438, 0x0cf0 }, { 0xa438, 0x0c80 }, { 0xa438, 0xd501 }, + { 0xa438, 0xce01 }, { 0xa438, 0xd70c }, { 0xa438, 0x6147 }, + { 0xa438, 0xa480 }, { 0xa438, 0x8440 }, { 0xa438, 0x8420 }, + { 0xa438, 0x8410 }, { 0xa438, 0xce00 }, { 0xa438, 0xd505 }, + { 0xa438, 0x0c0f }, { 0xa438, 0x0801 }, { 0xa438, 0xf002 }, + { 0xa438, 0xa4f0 }, { 0xa438, 0xce00 }, { 0xa438, 0xd500 }, + { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, { 0xa438, 0x1000 }, + { 0xa438, 0x1829 }, { 0xa438, 0xd73e }, { 0xa438, 0x6074 }, + { 0xa438, 0xd718 }, { 0xa438, 0x5f2d }, { 0xa438, 0x1000 }, + { 0xa438, 0x81b7 }, { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, + { 0xa438, 0x1000 }, { 0xa438, 0x1829 }, { 0xa438, 0xd73e }, + { 0xa438, 0x7f74 }, { 0xa438, 0x1000 }, { 0xa438, 0x81ce }, + { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, { 0xa438, 0x1000 }, + { 0xa438, 0x1829 }, { 0xa438, 0xd718 }, { 0xa438, 0x5f6d }, + { 0xa438, 0x1800 }, { 0xa438, 0x1660 }, { 0xa438, 0xd75e }, + { 0xa438, 0x68b1 }, { 0xa438, 0xd504 }, { 0xa438, 0xd71e }, + { 0xa438, 0x667b }, { 0xa438, 0x645a }, { 0xa438, 0x6239 }, + { 0xa438, 0x0cf0 }, { 0xa438, 0x0c10 }, { 0xa438, 0xd505 }, + { 0xa438, 0x0c0f }, { 0xa438, 0x0808 }, { 0xa438, 0xd501 }, + { 0xa438, 0xce01 }, { 0xa438, 0xd70c }, { 0xa438, 0x60c7 }, + { 0xa438, 0x8480 }, { 0xa438, 0x8440 }, { 0xa438, 0x8420 }, + { 0xa438, 0xa410 }, { 0xa438, 0xf032 }, { 0xa438, 0xa4f0 }, + { 0xa438, 0xf030 }, { 0xa438, 0x0cf0 }, { 0xa438, 0x0c20 }, + { 0xa438, 0xd505 }, { 0xa438, 0x0c0f }, { 0xa438, 0x0804 }, + { 0xa438, 0xd501 }, { 0xa438, 0xce01 }, { 0xa438, 0xd70c }, + { 0xa438, 0x60c7 }, { 0xa438, 0x8480 }, { 0xa438, 0x8440 }, + { 0xa438, 0xa420 }, { 0xa438, 0x8410 }, { 0xa438, 0xf022 }, + { 0xa438, 0xa4f0 }, { 0xa438, 0xf020 }, { 0xa438, 0x0cf0 }, + { 0xa438, 0x0c40 }, { 0xa438, 0xd505 }, { 0xa438, 0x0c0f }, + { 0xa438, 0x0802 }, { 0xa438, 0xd501 }, { 0xa438, 0xce01 }, + { 0xa438, 0xd70c }, { 0xa438, 0x60c7 }, { 0xa438, 0x8480 }, + { 0xa438, 0xa440 }, { 0xa438, 0x8420 }, { 0xa438, 0x8410 }, + { 0xa438, 0xf012 }, { 0xa438, 0xa4f0 }, { 0xa438, 0xf010 }, + { 0xa438, 0x0cf0 }, { 0xa438, 0x0c80 }, { 0xa438, 0xd505 }, + { 0xa438, 0x0c0f }, { 0xa438, 0x0801 }, { 0xa438, 0xd501 }, + { 0xa438, 0xce01 }, { 0xa438, 0xd70c }, { 0xa438, 0x60c7 }, + { 0xa438, 0xa480 }, { 0xa438, 0x8440 }, { 0xa438, 0x8420 }, + { 0xa438, 0x8410 }, { 0xa438, 0xf002 }, { 0xa438, 0xa4f0 }, + { 0xa438, 0x1800 }, { 0xa438, 0x168c }, { 0xa438, 0xd500 }, + { 0xa438, 0xd706 }, { 0xa438, 0x2529 }, { 0xa438, 0x80e0 }, + { 0xa438, 0xd718 }, { 0xa438, 0x607b }, { 0xa438, 0x40da }, + { 0xa438, 0xf00f }, { 0xa438, 0x431a }, { 0xa438, 0xf021 }, + { 0xa438, 0xd718 }, { 0xa438, 0x617b }, { 0xa438, 0x1000 }, + { 0xa438, 0x1a8a }, { 0xa438, 0x1000 }, { 0xa438, 0x1b1a }, + { 0xa438, 0xd718 }, { 0xa438, 0x608e }, { 0xa438, 0xd73e }, + { 0xa438, 0x5f34 }, { 0xa438, 0xf020 }, { 0xa438, 0xf053 }, + { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, { 0xa438, 0x1000 }, + { 0xa438, 0x1b1a }, { 0xa438, 0xd718 }, { 0xa438, 0x608e }, + { 0xa438, 0xd73e }, { 0xa438, 0x5f34 }, { 0xa438, 0xf023 }, + { 0xa438, 0xf067 }, { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, + { 0xa438, 0x1000 }, { 0xa438, 0x1b1a }, { 0xa438, 0xd718 }, + { 0xa438, 0x608e }, { 0xa438, 0xd73e }, { 0xa438, 0x5f34 }, + { 0xa438, 0xf026 }, { 0xa438, 0xf07b }, { 0xa438, 0x1000 }, + { 0xa438, 0x1a8a }, { 0xa438, 0x1000 }, { 0xa438, 0x1b1a }, + { 0xa438, 0xd718 }, { 0xa438, 0x608e }, { 0xa438, 0xd73e }, + { 0xa438, 0x5f34 }, { 0xa438, 0xf029 }, { 0xa438, 0xf08f }, + { 0xa438, 0x1000 }, { 0xa438, 0x81b7 }, { 0xa438, 0x1000 }, + { 0xa438, 0x1a8a }, { 0xa438, 0xd73e }, { 0xa438, 0x7fb4 }, + { 0xa438, 0x1000 }, { 0xa438, 0x81ce }, { 0xa438, 0x1000 }, + { 0xa438, 0x1a8a }, { 0xa438, 0xd718 }, { 0xa438, 0x5fae }, + { 0xa438, 0xf028 }, { 0xa438, 0x1000 }, { 0xa438, 0x81b7 }, + { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, { 0xa438, 0xd73e }, + { 0xa438, 0x7fb4 }, { 0xa438, 0x1000 }, { 0xa438, 0x81ce }, + { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, { 0xa438, 0xd718 }, + { 0xa438, 0x5fae }, { 0xa438, 0xf039 }, { 0xa438, 0x1000 }, + { 0xa438, 0x81b7 }, { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, + { 0xa438, 0xd73e }, { 0xa438, 0x7fb4 }, { 0xa438, 0x1000 }, + { 0xa438, 0x81ce }, { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, + { 0xa438, 0xd718 }, { 0xa438, 0x5fae }, { 0xa438, 0xf04a }, + { 0xa438, 0x1000 }, { 0xa438, 0x81b7 }, { 0xa438, 0x1000 }, + { 0xa438, 0x1a8a }, { 0xa438, 0xd73e }, { 0xa438, 0x7fb4 }, + { 0xa438, 0x1000 }, { 0xa438, 0x81ce }, { 0xa438, 0x1000 }, + { 0xa438, 0x1a8a }, { 0xa438, 0xd718 }, { 0xa438, 0x5fae }, + { 0xa438, 0xf05b }, { 0xa438, 0xd719 }, { 0xa438, 0x4119 }, + { 0xa438, 0xd504 }, { 0xa438, 0xac01 }, { 0xa438, 0xae01 }, + { 0xa438, 0xd500 }, { 0xa438, 0x1000 }, { 0xa438, 0x1a78 }, + { 0xa438, 0xf00a }, { 0xa438, 0xd719 }, { 0xa438, 0x4118 }, + { 0xa438, 0xd504 }, { 0xa438, 0xac11 }, { 0xa438, 0xd501 }, + { 0xa438, 0xce01 }, { 0xa438, 0xa410 }, { 0xa438, 0xce00 }, + { 0xa438, 0xd500 }, { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, + { 0xa438, 0xd718 }, { 0xa438, 0x5fb0 }, { 0xa438, 0xd505 }, + { 0xa438, 0xd719 }, { 0xa438, 0x4079 }, { 0xa438, 0xa80f }, + { 0xa438, 0xf05d }, { 0xa438, 0x4b98 }, { 0xa438, 0xa808 }, + { 0xa438, 0xf05a }, { 0xa438, 0xd719 }, { 0xa438, 0x4119 }, + { 0xa438, 0xd504 }, { 0xa438, 0xac02 }, { 0xa438, 0xae01 }, + { 0xa438, 0xd500 }, { 0xa438, 0x1000 }, { 0xa438, 0x1a78 }, + { 0xa438, 0xf00a }, { 0xa438, 0xd719 }, { 0xa438, 0x4118 }, + { 0xa438, 0xd504 }, { 0xa438, 0xac22 }, { 0xa438, 0xd501 }, + { 0xa438, 0xce01 }, { 0xa438, 0xa420 }, { 0xa438, 0xce00 }, + { 0xa438, 0xd500 }, { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, + { 0xa438, 0xd718 }, { 0xa438, 0x5fb0 }, { 0xa438, 0xd505 }, + { 0xa438, 0xd719 }, { 0xa438, 0x4079 }, { 0xa438, 0xa80f }, + { 0xa438, 0xf03f }, { 0xa438, 0x47d8 }, { 0xa438, 0xa804 }, + { 0xa438, 0xf03c }, { 0xa438, 0xd719 }, { 0xa438, 0x4119 }, + { 0xa438, 0xd504 }, { 0xa438, 0xac04 }, { 0xa438, 0xae01 }, + { 0xa438, 0xd500 }, { 0xa438, 0x1000 }, { 0xa438, 0x1a78 }, + { 0xa438, 0xf00a }, { 0xa438, 0xd719 }, { 0xa438, 0x4118 }, + { 0xa438, 0xd504 }, { 0xa438, 0xac44 }, { 0xa438, 0xd501 }, + { 0xa438, 0xce01 }, { 0xa438, 0xa440 }, { 0xa438, 0xce00 }, + { 0xa438, 0xd500 }, { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, + { 0xa438, 0xd718 }, { 0xa438, 0x5fb0 }, { 0xa438, 0xd505 }, + { 0xa438, 0xd719 }, { 0xa438, 0x4079 }, { 0xa438, 0xa80f }, + { 0xa438, 0xf021 }, { 0xa438, 0x4418 }, { 0xa438, 0xa802 }, + { 0xa438, 0xf01e }, { 0xa438, 0xd719 }, { 0xa438, 0x4119 }, + { 0xa438, 0xd504 }, { 0xa438, 0xac08 }, { 0xa438, 0xae01 }, + { 0xa438, 0xd500 }, { 0xa438, 0x1000 }, { 0xa438, 0x1a78 }, + { 0xa438, 0xf00a }, { 0xa438, 0xd719 }, { 0xa438, 0x4118 }, + { 0xa438, 0xd504 }, { 0xa438, 0xac88 }, { 0xa438, 0xd501 }, + { 0xa438, 0xce01 }, { 0xa438, 0xa480 }, { 0xa438, 0xce00 }, + { 0xa438, 0xd500 }, { 0xa438, 0x1000 }, { 0xa438, 0x1a8a }, + { 0xa438, 0xd718 }, { 0xa438, 0x5fb0 }, { 0xa438, 0xd505 }, + { 0xa438, 0xd719 }, { 0xa438, 0x4079 }, { 0xa438, 0xa80f }, + { 0xa438, 0xf003 }, { 0xa438, 0x4058 }, { 0xa438, 0xa801 }, + { 0xa438, 0x1800 }, { 0xa438, 0x1736 }, { 0xa438, 0xd73e }, + { 0xa438, 0xd505 }, { 0xa438, 0x3088 }, { 0xa438, 0x81c0 }, + { 0xa438, 0x61d3 }, { 0xa438, 0x6172 }, { 0xa438, 0x6111 }, + { 0xa438, 0x60b0 }, { 0xa438, 0xf00d }, { 0xa438, 0x3298 }, + { 0xa438, 0x81cb }, { 0xa438, 0xf00a }, { 0xa438, 0xa808 }, + { 0xa438, 0xf008 }, { 0xa438, 0xa804 }, { 0xa438, 0xf006 }, + { 0xa438, 0xa802 }, { 0xa438, 0xf004 }, { 0xa438, 0xa801 }, + { 0xa438, 0xf002 }, { 0xa438, 0xa80f }, { 0xa438, 0xd500 }, + { 0xa438, 0x0800 }, { 0xa438, 0xd505 }, { 0xa438, 0xd75e }, + { 0xa438, 0x6211 }, { 0xa438, 0xd71e }, { 0xa438, 0x619b }, + { 0xa438, 0x611a }, { 0xa438, 0x6099 }, { 0xa438, 0x0c0f }, + { 0xa438, 0x0808 }, { 0xa438, 0xf009 }, { 0xa438, 0x0c0f }, + { 0xa438, 0x0804 }, { 0xa438, 0xf006 }, { 0xa438, 0x0c0f }, + { 0xa438, 0x0802 }, { 0xa438, 0xf003 }, { 0xa438, 0x0c0f }, + { 0xa438, 0x0801 }, { 0xa438, 0xd500 }, { 0xa438, 0x0800 }, + { 0xa436, 0xa026 }, { 0xa438, 0xffff }, { 0xa436, 0xa024 }, + { 0xa438, 0xffff }, { 0xa436, 0xa022 }, { 0xa438, 0xffff }, + { 0xa436, 0xa020 }, { 0xa438, 0xffff }, { 0xa436, 0xa006 }, + { 0xa438, 0xffff }, { 0xa436, 0xa004 }, { 0xa438, 0x16ab }, + { 0xa436, 0xa002 }, { 0xa438, 0x1663 }, { 0xa436, 0xa000 }, + { 0xa438, 0x1608 }, { 0xa436, 0xa008 }, { 0xa438, 0x0700 }, + { 0xa436, 0xa016 }, { 0xa438, 0x0000 }, { 0xa436, 0xa012 }, + { 0xa438, 0x07f8 }, { 0xa436, 0xa014 }, { 0xa438, 0xcc01 }, + { 0xa438, 0x20f6 }, { 0xa438, 0x0000 }, { 0xa438, 0x0000 }, + { 0xa438, 0x0000 }, { 0xa438, 0x0000 }, { 0xa438, 0x0000 }, + { 0xa438, 0x0000 }, { 0xa436, 0xa152 }, { 0xa438, 0x021c }, + { 0xa436, 0xa154 }, { 0xa438, 0x2100 }, { 0xa436, 0xa156 }, + { 0xa438, 0x3fff }, { 0xa436, 0xa158 }, { 0xa438, 0x3fff }, + { 0xa436, 0xa15a }, { 0xa438, 0x3fff }, { 0xa436, 0xa15c }, + { 0xa438, 0x3fff }, { 0xa436, 0xa15e }, { 0xa438, 0x3fff }, + { 0xa436, 0xa160 }, { 0xa438, 0x3fff }, { 0xa436, 0xa150 }, + { 0xa438, 0x0003 }, { 0xa436, 0xa016 }, { 0xa438, 0x0010 }, + { 0xa436, 0xa012 }, { 0xa438, 0x0000 }, { 0xa436, 0xa014 }, + { 0xa438, 0x1800 }, { 0xa438, 0x8010 }, { 0xa438, 0x1800 }, + { 0xa438, 0x8014 }, { 0xa438, 0x1800 }, { 0xa438, 0x803d }, + { 0xa438, 0x1800 }, { 0xa438, 0x804a }, { 0xa438, 0x1800 }, + { 0xa438, 0x804e }, { 0xa438, 0x1800 }, { 0xa438, 0x8052 }, + { 0xa438, 0x1800 }, { 0xa438, 0x8092 }, { 0xa438, 0x1800 }, + { 0xa438, 0x80a0 }, { 0xa438, 0xc2ff }, { 0xa438, 0x9a40 }, + { 0xa438, 0x1800 }, { 0xa438, 0x0042 }, { 0xa438, 0x1000 }, + { 0xa438, 0x02e5 }, { 0xa438, 0xba20 }, { 0xa438, 0x1000 }, + { 0xa438, 0x02b4 }, { 0xa438, 0xd701 }, { 0xa438, 0x4103 }, + { 0xa438, 0xd700 }, { 0xa438, 0x5f6c }, { 0xa438, 0x1000 }, + { 0xa438, 0x8024 }, { 0xa438, 0x9a20 }, { 0xa438, 0x1800 }, + { 0xa438, 0x0073 }, { 0xa438, 0x1800 }, { 0xa438, 0x0084 }, + { 0xa438, 0xd701 }, { 0xa438, 0x4061 }, { 0xa438, 0xba0f }, + { 0xa438, 0xf004 }, { 0xa438, 0x4060 }, { 0xa438, 0x1000 }, + { 0xa438, 0x802d }, { 0xa438, 0xba10 }, { 0xa438, 0x0800 }, + { 0xa438, 0xd700 }, { 0xa438, 0x60bb }, { 0xa438, 0x611c }, + { 0xa438, 0x0c0f }, { 0xa438, 0x1a01 }, { 0xa438, 0xf00a }, + { 0xa438, 0x60fc }, { 0xa438, 0x0c0f }, { 0xa438, 0x1a02 }, + { 0xa438, 0xf006 }, { 0xa438, 0x0c0f }, { 0xa438, 0x1a04 }, + { 0xa438, 0xf003 }, { 0xa438, 0x0c0f }, { 0xa438, 0x1a08 }, + { 0xa438, 0x0800 }, { 0xa438, 0x0c0f }, { 0xa438, 0x0504 }, + { 0xa438, 0xad02 }, { 0xa438, 0xd73e }, { 0xa438, 0x40f6 }, + { 0xa438, 0x1000 }, { 0xa438, 0x02c0 }, { 0xa438, 0xd700 }, + { 0xa438, 0x5fac }, { 0xa438, 0x1000 }, { 0xa438, 0x8024 }, + { 0xa438, 0x1800 }, { 0xa438, 0x0139 }, { 0xa438, 0x9a3f }, + { 0xa438, 0x8bf0 }, { 0xa438, 0x1800 }, { 0xa438, 0x02df }, + { 0xa438, 0x9a3f }, { 0xa438, 0x9910 }, { 0xa438, 0x1800 }, + { 0xa438, 0x02d7 }, { 0xa438, 0xad02 }, { 0xa438, 0x8d01 }, + { 0xa438, 0x9a7f }, { 0xa438, 0x9910 }, { 0xa438, 0x9860 }, + { 0xa438, 0xcb00 }, { 0xa438, 0xd501 }, { 0xa438, 0xce01 }, + { 0xa438, 0x85f0 }, { 0xa438, 0xd500 }, { 0xa438, 0x0c0f }, + { 0xa438, 0x0505 }, { 0xa438, 0xb820 }, { 0xa438, 0xc000 }, + { 0xa438, 0xc100 }, { 0xa438, 0xc628 }, { 0xa438, 0xc700 }, + { 0xa438, 0xc801 }, { 0xa438, 0xc91e }, { 0xa438, 0xc001 }, + { 0xa438, 0x4019 }, { 0xa438, 0xc6f8 }, { 0xa438, 0xc702 }, + { 0xa438, 0xc809 }, { 0xa438, 0xc940 }, { 0xa438, 0xc002 }, + { 0xa438, 0x4019 }, { 0xa438, 0x1000 }, { 0xa438, 0x02cc }, + { 0xa438, 0xd700 }, { 0xa438, 0x5fa7 }, { 0xa438, 0xc010 }, + { 0xa438, 0x1000 }, { 0xa438, 0x02cc }, { 0xa438, 0xd700 }, + { 0xa438, 0x5fa0 }, { 0xa438, 0xc020 }, { 0xa438, 0x1000 }, + { 0xa438, 0x02cc }, { 0xa438, 0xd700 }, { 0xa438, 0x5fa1 }, + { 0xa438, 0x0c0f }, { 0xa438, 0x0506 }, { 0xa438, 0xb840 }, + { 0xa438, 0xc6ca }, { 0xa438, 0xc701 }, { 0xa438, 0xc809 }, + { 0xa438, 0xc900 }, { 0xa438, 0xc001 }, { 0xa438, 0x4019 }, + { 0xa438, 0xc6b8 }, { 0xa438, 0xc700 }, { 0xa438, 0xc800 }, + { 0xa438, 0xc900 }, { 0xa438, 0xc008 }, { 0xa438, 0x4019 }, + { 0xa438, 0x1000 }, { 0xa438, 0x02cc }, { 0xa438, 0xd700 }, + { 0xa438, 0x5fa5 }, { 0xa438, 0x8580 }, { 0xa438, 0x8d02 }, + { 0xa438, 0x1800 }, { 0xa438, 0x018f }, { 0xa438, 0x1000 }, + { 0xa438, 0x02cc }, { 0xa438, 0xd700 }, { 0xa438, 0x6124 }, + { 0xa438, 0xd73e }, { 0xa438, 0x5f75 }, { 0xa438, 0xd700 }, + { 0xa438, 0x5f2c }, { 0xa438, 0x1000 }, { 0xa438, 0x8024 }, + { 0xa438, 0x9a20 }, { 0xa438, 0xfff5 }, { 0xa438, 0x1800 }, + { 0xa438, 0x00b8 }, { 0xa438, 0x0c0f }, { 0xa438, 0x0503 }, + { 0xa438, 0xad02 }, { 0xa438, 0x68c8 }, { 0xa438, 0x1000 }, + { 0xa438, 0x02c0 }, { 0xa438, 0xd700 }, { 0xa438, 0x6848 }, + { 0xa438, 0x604d }, { 0xa438, 0xfffb }, { 0xa438, 0xd73e }, + { 0xa438, 0x6082 }, { 0xa438, 0x1000 }, { 0xa438, 0x02a1 }, + { 0xa438, 0x8a0f }, { 0xa438, 0x1000 }, { 0xa438, 0x02c0 }, + { 0xa438, 0xd700 }, { 0xa438, 0x5fae }, { 0xa438, 0x1000 }, + { 0xa438, 0x02de }, { 0xa438, 0x1000 }, { 0xa438, 0x02c0 }, + { 0xa438, 0xd700 }, { 0xa438, 0x5faf }, { 0xa438, 0x8d01 }, + { 0xa438, 0x8b0f }, { 0xa438, 0x1000 }, { 0xa438, 0x02c0 }, + { 0xa438, 0xd700 }, { 0xa438, 0x2a58 }, { 0xa438, 0x80c5 }, + { 0xa438, 0x2a5b }, { 0xa438, 0x80cd }, { 0xa438, 0x2b53 }, + { 0xa438, 0x80d9 }, { 0xa438, 0xfff7 }, { 0xa438, 0x1000 }, + { 0xa438, 0x022a }, { 0xa438, 0x1000 }, { 0xa438, 0x02e5 }, + { 0xa438, 0xba40 }, { 0xa438, 0x1000 }, { 0xa438, 0x02fd }, + { 0xa438, 0xf018 }, { 0xa438, 0x1000 }, { 0xa438, 0x022a }, + { 0xa438, 0x1000 }, { 0xa438, 0x02e5 }, { 0xa438, 0xba40 }, + { 0xa438, 0x1000 }, { 0xa438, 0x02c0 }, { 0xa438, 0xd700 }, + { 0xa438, 0x5faa }, { 0xa438, 0x1000 }, { 0xa438, 0x02fd }, + { 0xa438, 0xf00c }, { 0xa438, 0x1000 }, { 0xa438, 0x022a }, + { 0xa438, 0x1000 }, { 0xa438, 0x02fd }, { 0xa438, 0x1000 }, + { 0xa438, 0x02c0 }, { 0xa438, 0xd700 }, { 0xa438, 0x5fab }, + { 0xa438, 0x1000 }, { 0xa438, 0x02e5 }, { 0xa438, 0xba40 }, + { 0xa438, 0x1000 }, { 0xa438, 0x02c0 }, { 0xa438, 0xd700 }, + { 0xa438, 0x6088 }, { 0xa438, 0xfffc }, { 0xa438, 0x1800 }, + { 0xa438, 0x0120 }, { 0xa438, 0x1800 }, { 0xa438, 0x0122 }, + { 0xa436, 0xa08e }, { 0xa438, 0x00db }, { 0xa436, 0xa08c }, + { 0xa438, 0x00b4 }, { 0xa436, 0xa08a }, { 0xa438, 0x015a }, + { 0xa436, 0xa088 }, { 0xa438, 0x02d6 }, { 0xa436, 0xa086 }, + { 0xa438, 0x02de }, { 0xa436, 0xa084 }, { 0xa438, 0x0137 }, + { 0xa436, 0xa082 }, { 0xa438, 0x0071 }, { 0xa436, 0xa080 }, + { 0xa438, 0x0041 }, { 0xa436, 0xa090 }, { 0xa438, 0x00ff }, + { 0xa436, 0xa016 }, { 0xa438, 0x0020 }, { 0xa436, 0xa012 }, + { 0xa438, 0x0000 }, { 0xa436, 0xa014 }, { 0xa438, 0x1800 }, + { 0xa438, 0x8010 }, { 0xa438, 0x1800 }, { 0xa438, 0x801d }, + { 0xa438, 0x1800 }, { 0xa438, 0x808a }, { 0xa438, 0x1800 }, + { 0xa438, 0x80a5 }, { 0xa438, 0x1800 }, { 0xa438, 0x80b8 }, + { 0xa438, 0x1800 }, { 0xa438, 0x8108 }, { 0xa438, 0x1800 }, + { 0xa438, 0x810f }, { 0xa438, 0x1800 }, { 0xa438, 0x811b }, + { 0xa438, 0x8980 }, { 0xa438, 0xd702 }, { 0xa438, 0x6126 }, + { 0xa438, 0xd704 }, { 0xa438, 0x4063 }, { 0xa438, 0xd702 }, + { 0xa438, 0x6060 }, { 0xa438, 0xd702 }, { 0xa438, 0x6077 }, + { 0xa438, 0x1800 }, { 0xa438, 0x0c29 }, { 0xa438, 0x1800 }, + { 0xa438, 0x0c2b }, { 0xa438, 0x1000 }, { 0xa438, 0x115a }, + { 0xa438, 0xd71f }, { 0xa438, 0x5fb4 }, { 0xa438, 0xd702 }, + { 0xa438, 0x6c46 }, { 0xa438, 0xd704 }, { 0xa438, 0x4063 }, + { 0xa438, 0xd702 }, { 0xa438, 0x6060 }, { 0xa438, 0xd702 }, + { 0xa438, 0x6b97 }, { 0xa438, 0xa340 }, { 0xa438, 0x0c06 }, + { 0xa438, 0x0102 }, { 0xa438, 0xce01 }, { 0xa438, 0x1000 }, + { 0xa438, 0x117a }, { 0xa438, 0xa240 }, { 0xa438, 0xa902 }, + { 0xa438, 0xa204 }, { 0xa438, 0xa280 }, { 0xa438, 0xa364 }, + { 0xa438, 0xab02 }, { 0xa438, 0x8380 }, { 0xa438, 0xa00a }, + { 0xa438, 0xcd8d }, { 0xa438, 0x1000 }, { 0xa438, 0x115a }, + { 0xa438, 0xd706 }, { 0xa438, 0x5fb5 }, { 0xa438, 0xb920 }, + { 0xa438, 0x1000 }, { 0xa438, 0x115a }, { 0xa438, 0xd71f }, + { 0xa438, 0x7fb4 }, { 0xa438, 0x9920 }, { 0xa438, 0x1000 }, + { 0xa438, 0x115a }, { 0xa438, 0xd71f }, { 0xa438, 0x6065 }, + { 0xa438, 0x7c74 }, { 0xa438, 0xfffb }, { 0xa438, 0xb820 }, + { 0xa438, 0x1000 }, { 0xa438, 0x115a }, { 0xa438, 0xd71f }, + { 0xa438, 0x7fa5 }, { 0xa438, 0x9820 }, { 0xa438, 0xa410 }, + { 0xa438, 0x8902 }, { 0xa438, 0xa120 }, { 0xa438, 0xa380 }, + { 0xa438, 0xce02 }, { 0xa438, 0x1000 }, { 0xa438, 0x117a }, + { 0xa438, 0x8280 }, { 0xa438, 0xa324 }, { 0xa438, 0xab02 }, + { 0xa438, 0xa00a }, { 0xa438, 0x8118 }, { 0xa438, 0x863f }, + { 0xa438, 0x87fb }, { 0xa438, 0xcd8e }, { 0xa438, 0xd193 }, + { 0xa438, 0xd047 }, { 0xa438, 0x1000 }, { 0xa438, 0x115a }, + { 0xa438, 0x1000 }, { 0xa438, 0x115f }, { 0xa438, 0xd700 }, + { 0xa438, 0x5f7b }, { 0xa438, 0xa280 }, { 0xa438, 0x1000 }, + { 0xa438, 0x115a }, { 0xa438, 0x1000 }, { 0xa438, 0x115f }, + { 0xa438, 0xd706 }, { 0xa438, 0x5f78 }, { 0xa438, 0xa210 }, + { 0xa438, 0xd700 }, { 0xa438, 0x6083 }, { 0xa438, 0xd101 }, + { 0xa438, 0xd047 }, { 0xa438, 0xf003 }, { 0xa438, 0xd160 }, + { 0xa438, 0xd04b }, { 0xa438, 0x1000 }, { 0xa438, 0x115a }, + { 0xa438, 0x1000 }, { 0xa438, 0x115f }, { 0xa438, 0xd700 }, + { 0xa438, 0x5f7b }, { 0xa438, 0x1000 }, { 0xa438, 0x115a }, + { 0xa438, 0x1000 }, { 0xa438, 0x115f }, { 0xa438, 0xd706 }, + { 0xa438, 0x5f79 }, { 0xa438, 0x8120 }, { 0xa438, 0xbb20 }, + { 0xa438, 0x1800 }, { 0xa438, 0x0c8b }, { 0xa438, 0x0c03 }, + { 0xa438, 0x1502 }, { 0xa438, 0x8f80 }, { 0xa438, 0x9503 }, + { 0xa438, 0x1800 }, { 0xa438, 0x0c3c }, { 0xa438, 0x0c03 }, + { 0xa438, 0x1502 }, { 0xa438, 0xa608 }, { 0xa438, 0x9503 }, + { 0xa438, 0x0c03 }, { 0xa438, 0x1502 }, { 0xa438, 0x8f80 }, + { 0xa438, 0x9503 }, { 0xa438, 0xd704 }, { 0xa438, 0x6192 }, + { 0xa438, 0xd702 }, { 0xa438, 0x4116 }, { 0xa438, 0xce04 }, + { 0xa438, 0x1000 }, { 0xa438, 0x117a }, { 0xa438, 0x0c03 }, + { 0xa438, 0x1502 }, { 0xa438, 0x8f40 }, { 0xa438, 0x9503 }, + { 0xa438, 0x1800 }, { 0xa438, 0x0b3d }, { 0xa438, 0x0c03 }, + { 0xa438, 0x1502 }, { 0xa438, 0xaf40 }, { 0xa438, 0x9503 }, + { 0xa438, 0x1800 }, { 0xa438, 0x0b48 }, { 0xa438, 0xd704 }, + { 0xa438, 0x6192 }, { 0xa438, 0xd702 }, { 0xa438, 0x4116 }, + { 0xa438, 0xce04 }, { 0xa438, 0x1000 }, { 0xa438, 0x117a }, + { 0xa438, 0x0c03 }, { 0xa438, 0x1502 }, { 0xa438, 0x8f40 }, + { 0xa438, 0x9503 }, { 0xa438, 0x1800 }, { 0xa438, 0x1269 }, + { 0xa438, 0x0c03 }, { 0xa438, 0x1502 }, { 0xa438, 0xaf40 }, + { 0xa438, 0x9503 }, { 0xa438, 0x1800 }, { 0xa438, 0x1274 }, + { 0xa438, 0x0c03 }, { 0xa438, 0x1502 }, { 0xa438, 0xa608 }, + { 0xa438, 0xc700 }, { 0xa438, 0x9503 }, { 0xa438, 0xce54 }, + { 0xa438, 0x1000 }, { 0xa438, 0x117a }, { 0xa438, 0xa290 }, + { 0xa438, 0xa304 }, { 0xa438, 0xab02 }, { 0xa438, 0xd700 }, + { 0xa438, 0x6050 }, { 0xa438, 0xab04 }, { 0xa438, 0x0c38 }, + { 0xa438, 0x0608 }, { 0xa438, 0xaa0b }, { 0xa438, 0xd702 }, + { 0xa438, 0x0c03 }, { 0xa438, 0x1502 }, { 0xa438, 0x8d01 }, + { 0xa438, 0xae40 }, { 0xa438, 0x4044 }, { 0xa438, 0x8e20 }, + { 0xa438, 0x9503 }, { 0xa438, 0x0c03 }, { 0xa438, 0x1502 }, + { 0xa438, 0x8c20 }, { 0xa438, 0x9503 }, { 0xa438, 0xd700 }, + { 0xa438, 0x6078 }, { 0xa438, 0xd700 }, { 0xa438, 0x609a }, + { 0xa438, 0xd109 }, { 0xa438, 0xd074 }, { 0xa438, 0xf003 }, + { 0xa438, 0xd109 }, { 0xa438, 0xd075 }, { 0xa438, 0x1000 }, + { 0xa438, 0x115a }, { 0xa438, 0xd704 }, { 0xa438, 0x6252 }, + { 0xa438, 0xd702 }, { 0xa438, 0x4116 }, { 0xa438, 0xce54 }, + { 0xa438, 0x1000 }, { 0xa438, 0x117a }, { 0xa438, 0x0c03 }, + { 0xa438, 0x1502 }, { 0xa438, 0x8f40 }, { 0xa438, 0x9503 }, + { 0xa438, 0xa00a }, { 0xa438, 0xd704 }, { 0xa438, 0x41e7 }, + { 0xa438, 0x0c03 }, { 0xa438, 0x1502 }, { 0xa438, 0xa570 }, + { 0xa438, 0x9503 }, { 0xa438, 0xf00a }, { 0xa438, 0x0c03 }, + { 0xa438, 0x1502 }, { 0xa438, 0xaf40 }, { 0xa438, 0x9503 }, + { 0xa438, 0x800a }, { 0xa438, 0x0c03 }, { 0xa438, 0x1502 }, + { 0xa438, 0x8570 }, { 0xa438, 0x9503 }, { 0xa438, 0xd704 }, + { 0xa438, 0x60f3 }, { 0xa438, 0xd71f }, { 0xa438, 0x60ee }, + { 0xa438, 0xd700 }, { 0xa438, 0x5bbe }, { 0xa438, 0x1800 }, + { 0xa438, 0x0e71 }, { 0xa438, 0x1800 }, { 0xa438, 0x0e7c }, + { 0xa438, 0x1800 }, { 0xa438, 0x0e7e }, { 0xa438, 0x0c03 }, + { 0xa438, 0x1502 }, { 0xa438, 0xaf80 }, { 0xa438, 0x9503 }, + { 0xa438, 0xcd62 }, { 0xa438, 0x1800 }, { 0xa438, 0x0bd2 }, + { 0xa438, 0x800a }, { 0xa438, 0x8530 }, { 0xa438, 0x0c03 }, + { 0xa438, 0x1502 }, { 0xa438, 0x8d10 }, { 0xa438, 0x9503 }, + { 0xa438, 0xd700 }, { 0xa438, 0x6050 }, { 0xa438, 0xaa20 }, + { 0xa438, 0x8306 }, { 0xa438, 0x1800 }, { 0xa438, 0x0cb6 }, + { 0xa438, 0xd105 }, { 0xa438, 0xd040 }, { 0xa438, 0x1000 }, + { 0xa438, 0x0d8f }, { 0xa438, 0xd700 }, { 0xa438, 0x5fbb }, + { 0xa438, 0x0c03 }, { 0xa438, 0x1502 }, { 0xa438, 0x8608 }, + { 0xa438, 0x9503 }, { 0xa438, 0x1000 }, { 0xa438, 0x0d8f }, + { 0xa438, 0xd704 }, { 0xa438, 0x7fb6 }, { 0xa438, 0x0c03 }, + { 0xa438, 0x1502 }, { 0xa438, 0x87f0 }, { 0xa438, 0x9503 }, + { 0xa438, 0xce88 }, { 0xa438, 0x1000 }, { 0xa438, 0x117a }, + { 0xa438, 0x0c03 }, { 0xa438, 0x1502 }, { 0xa438, 0xa608 }, + { 0xa438, 0x9503 }, { 0xa438, 0xd73e }, { 0xa438, 0x60a5 }, + { 0xa438, 0xd705 }, { 0xa438, 0x4071 }, { 0xa438, 0x1800 }, + { 0xa438, 0x0d65 }, { 0xa438, 0x1800 }, { 0xa438, 0x0d6f }, + { 0xa436, 0xa10e }, { 0xa438, 0x0d58 }, { 0xa436, 0xa10c }, + { 0xa438, 0x0cb5 }, { 0xa436, 0xa10a }, { 0xa438, 0x0bd1 }, + { 0xa436, 0xa108 }, { 0xa438, 0x0e37 }, { 0xa436, 0xa106 }, + { 0xa438, 0x1267 }, { 0xa436, 0xa104 }, { 0xa438, 0x0b3b }, + { 0xa436, 0xa102 }, { 0xa438, 0x0c38 }, { 0xa436, 0xa100 }, + { 0xa438, 0x0c24 }, { 0xa436, 0xa110 }, { 0xa438, 0x00ff }, + { 0xa436, 0xa016 }, { 0xa438, 0x0020 }, { 0xa436, 0xa012 }, + { 0xa438, 0x1ff8 }, { 0xa436, 0xa014 }, { 0xa438, 0x0000 }, + { 0xa438, 0x0000 }, { 0xa438, 0x0000 }, { 0xa438, 0x0000 }, + { 0xa438, 0x0000 }, { 0xa438, 0x0000 }, { 0xa438, 0x0000 }, + { 0xa438, 0x0000 }, { 0xa436, 0xa164 }, { 0xa438, 0x0ceb }, + { 0xa436, 0xa166 }, { 0xa438, 0x0e73 }, { 0xa436, 0xa168 }, + { 0xa438, 0x0deb }, { 0xa436, 0xa16a }, { 0xa438, 0x3fff }, + { 0xa436, 0xa16c }, { 0xa438, 0x3fff }, { 0xa436, 0xa16e }, + { 0xa438, 0x3fff }, { 0xa436, 0xa170 }, { 0xa438, 0x3fff }, + { 0xa436, 0xa172 }, { 0xa438, 0x3fff }, { 0xa436, 0xa162 }, + { 0xa438, 0x0007 }, { 0xa436, 0xb87c }, { 0xa438, 0x85bf }, + { 0xa436, 0xb87e }, { 0xa438, 0xaf85 }, { 0xa438, 0xd7af }, + { 0xa438, 0x85fb }, { 0xa438, 0xaf86 }, { 0xa438, 0x10af }, + { 0xa438, 0x8638 }, { 0xa438, 0xaf86 }, { 0xa438, 0x47af }, + { 0xa438, 0x8647 }, { 0xa438, 0xaf86 }, { 0xa438, 0x47af }, + { 0xa438, 0x8647 }, { 0xa438, 0xbf85 }, { 0xa438, 0xf802 }, + { 0xa438, 0x627f }, { 0xa438, 0xbf61 }, { 0xa438, 0xc702 }, + { 0xa438, 0x627f }, { 0xa438, 0xae0c }, { 0xa438, 0xbf85 }, + { 0xa438, 0xf802 }, { 0xa438, 0x6276 }, { 0xa438, 0xbf61 }, + { 0xa438, 0xc702 }, { 0xa438, 0x6276 }, { 0xa438, 0xee85 }, + { 0xa438, 0x4200 }, { 0xa438, 0xaf1b }, { 0xa438, 0x2333 }, + { 0xa438, 0xa484 }, { 0xa438, 0xbf86 }, { 0xa438, 0x0a02 }, + { 0xa438, 0x627f }, { 0xa438, 0xbf86 }, { 0xa438, 0x0d02 }, + { 0xa438, 0x627f }, { 0xa438, 0xaf1b }, { 0xa438, 0x8422 }, + { 0xa438, 0xa484 }, { 0xa438, 0x66ac }, { 0xa438, 0x0ef8 }, + { 0xa438, 0xfbef }, { 0xa438, 0x79fb }, { 0xa438, 0xe080 }, + { 0xa438, 0x16ad }, { 0xa438, 0x230f }, { 0xa438, 0xee85 }, + { 0xa438, 0x4200 }, { 0xa438, 0x1f44 }, { 0xa438, 0xbf86 }, + { 0xa438, 0x30d7 }, { 0xa438, 0x0008 }, { 0xa438, 0x0264 }, + { 0xa438, 0xa3ff }, { 0xa438, 0xef97 }, { 0xa438, 0xfffc }, + { 0xa438, 0x0485 }, { 0xa438, 0xf861 }, { 0xa438, 0xc786 }, + { 0xa438, 0x0a86 }, { 0xa438, 0x0de1 }, { 0xa438, 0x8feb }, + { 0xa438, 0xe583 }, { 0xa438, 0x20e1 }, { 0xa438, 0x8fea }, + { 0xa438, 0xe583 }, { 0xa438, 0x21af }, { 0xa438, 0x41a7 }, + { 0xa436, 0xb85e }, { 0xa438, 0x1b05 }, { 0xa436, 0xb860 }, + { 0xa438, 0x1b78 }, { 0xa436, 0xb862 }, { 0xa438, 0x1a08 }, + { 0xa436, 0xb864 }, { 0xa438, 0x419f }, { 0xa436, 0xb886 }, + { 0xa438, 0xffff }, { 0xa436, 0xb888 }, { 0xa438, 0xffff }, + { 0xa436, 0xb88a }, { 0xa438, 0xffff }, { 0xa436, 0xb88c }, + { 0xa438, 0xffff }, { 0xa436, 0xb838 }, { 0xa438, 0x000f }, + { 0xb820, 0x0010 }, { 0xa436, 0x0000 }, { 0xa438, 0x0000 }, + { 0xb82e, 0x0000 }, { 0xa436, 0x8023 }, { 0xa438, 0x0000 }, + { 0xa436, 0x801e }, { 0xa438, 0x0013 }, { 0xb820, 0x0000 }, + { 0xa436, 0xacca }, { 0xa438, 0x0104 }, { 0xa436, 0xaccc }, + { 0xa438, 0x8000 }, { 0xa436, 0xacce }, { 0xa438, 0xffff }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0fff }, { 0xa436, 0xacce }, + { 0xa438, 0xfd47 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0fff }, + { 0xa436, 0xacce }, { 0xa438, 0xffff }, { 0xa436, 0xacd0 }, + { 0xa438, 0x07ff }, { 0xa436, 0xacce }, { 0xa438, 0xe56f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x01c0 }, { 0xa436, 0xacce }, + { 0xa438, 0xffff }, { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, + { 0xa436, 0xacce }, { 0xa438, 0xed97 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x01c8 }, { 0xa436, 0xacce }, { 0xa438, 0xffff }, + { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, { 0xa436, 0xacce }, + { 0xa438, 0xf5bf }, { 0xa436, 0xacd0 }, { 0xa438, 0x01d0 }, + { 0xa436, 0xacce }, { 0xa438, 0xfb07 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x07ff }, { 0xa436, 0xacce }, { 0xa438, 0xfb0f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x01d8 }, { 0xa436, 0xacce }, + { 0xa438, 0xa087 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0180 }, + { 0xa436, 0xacce }, { 0xa438, 0xa00f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0108 }, { 0xa436, 0xacce }, { 0xa438, 0xa807 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0100 }, { 0xa436, 0xacce }, + { 0xa438, 0xa88f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0188 }, + { 0xa436, 0xacce }, { 0xa438, 0xb027 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0120 }, { 0xa436, 0xacce }, { 0xa438, 0xb02f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0128 }, { 0xa436, 0xacce }, + { 0xa438, 0xb847 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0140 }, + { 0xa436, 0xacce }, { 0xa438, 0xb84f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0148 }, { 0xa436, 0xacce }, { 0xa438, 0xfb17 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, { 0xa436, 0xacce }, + { 0xa438, 0xfb1f }, { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, + { 0xa436, 0xacce }, { 0xa438, 0xa017 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0110 }, { 0xa436, 0xacce }, { 0xa438, 0xa01f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0118 }, { 0xa436, 0xacce }, + { 0xa438, 0xa837 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0130 }, + { 0xa436, 0xacce }, { 0xa438, 0xa83f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0138 }, { 0xa436, 0xacce }, { 0xa438, 0xb097 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0190 }, { 0xa436, 0xacce }, + { 0xa438, 0xb05f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0158 }, + { 0xa436, 0xacce }, { 0xa438, 0xb857 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0150 }, { 0xa436, 0xacce }, { 0xa438, 0xb89f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0198 }, { 0xa436, 0xacce }, + { 0xa438, 0xfb27 }, { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, + { 0xa436, 0xacce }, { 0xa438, 0xfb2f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x07ff }, { 0xa436, 0xacce }, { 0xa438, 0x8087 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0180 }, { 0xa436, 0xacce }, + { 0xa438, 0x800f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0108 }, + { 0xa436, 0xacce }, { 0xa438, 0x8807 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0100 }, { 0xa436, 0xacce }, { 0xa438, 0x888f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0188 }, { 0xa436, 0xacce }, + { 0xa438, 0x9027 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0120 }, + { 0xa436, 0xacce }, { 0xa438, 0x902f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0128 }, { 0xa436, 0xacce }, { 0xa438, 0x9847 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0140 }, { 0xa436, 0xacce }, + { 0xa438, 0x984f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0148 }, + { 0xa436, 0xacce }, { 0xa438, 0xa0a7 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x01a0 }, { 0xa436, 0xacce }, { 0xa438, 0xa8af }, + { 0xa436, 0xacd0 }, { 0xa438, 0x01a8 }, { 0xa436, 0xacce }, + { 0xa438, 0xa067 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0161 }, + { 0xa436, 0xacce }, { 0xa438, 0xa86f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0169 }, { 0xa436, 0xacce }, { 0xa438, 0xfb37 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, { 0xa436, 0xacce }, + { 0xa438, 0xfb3f }, { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, + { 0xa436, 0xacce }, { 0xa438, 0x8017 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0110 }, { 0xa436, 0xacce }, { 0xa438, 0x801f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0118 }, { 0xa436, 0xacce }, + { 0xa438, 0x8837 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0130 }, + { 0xa436, 0xacce }, { 0xa438, 0x883f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0138 }, { 0xa436, 0xacce }, { 0xa438, 0x9097 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0190 }, { 0xa436, 0xacce }, + { 0xa438, 0x905f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0158 }, + { 0xa436, 0xacce }, { 0xa438, 0x9857 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0150 }, { 0xa436, 0xacce }, { 0xa438, 0x989f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0198 }, { 0xa436, 0xacce }, + { 0xa438, 0xb0b7 }, { 0xa436, 0xacd0 }, { 0xa438, 0x01b0 }, + { 0xa436, 0xacce }, { 0xa438, 0xb8bf }, { 0xa436, 0xacd0 }, + { 0xa438, 0x01b8 }, { 0xa436, 0xacce }, { 0xa438, 0xb077 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0171 }, { 0xa436, 0xacce }, + { 0xa438, 0xb87f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0179 }, + { 0xa436, 0xacce }, { 0xa438, 0xfb47 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x07ff }, { 0xa436, 0xacce }, { 0xa438, 0xfb4f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, { 0xa436, 0xacce }, + { 0xa438, 0x6087 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0180 }, + { 0xa436, 0xacce }, { 0xa438, 0x600f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0108 }, { 0xa436, 0xacce }, { 0xa438, 0x6807 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0100 }, { 0xa436, 0xacce }, + { 0xa438, 0x688f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0188 }, + { 0xa436, 0xacce }, { 0xa438, 0x7027 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0120 }, { 0xa436, 0xacce }, { 0xa438, 0x702f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0128 }, { 0xa436, 0xacce }, + { 0xa438, 0x7847 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0140 }, + { 0xa436, 0xacce }, { 0xa438, 0x784f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0148 }, { 0xa436, 0xacce }, { 0xa438, 0x80a7 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x01a0 }, { 0xa436, 0xacce }, + { 0xa438, 0x88af }, { 0xa436, 0xacd0 }, { 0xa438, 0x01a8 }, + { 0xa436, 0xacce }, { 0xa438, 0x8067 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0161 }, { 0xa436, 0xacce }, { 0xa438, 0x886f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0169 }, { 0xa436, 0xacce }, + { 0xa438, 0xfb57 }, { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, + { 0xa436, 0xacce }, { 0xa438, 0xfb5f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x07ff }, { 0xa436, 0xacce }, { 0xa438, 0x6017 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0110 }, { 0xa436, 0xacce }, + { 0xa438, 0x601f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0118 }, + { 0xa436, 0xacce }, { 0xa438, 0x6837 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0130 }, { 0xa436, 0xacce }, { 0xa438, 0x683f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0138 }, { 0xa436, 0xacce }, + { 0xa438, 0x7097 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0190 }, + { 0xa436, 0xacce }, { 0xa438, 0x705f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0158 }, { 0xa436, 0xacce }, { 0xa438, 0x7857 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0150 }, { 0xa436, 0xacce }, + { 0xa438, 0x789f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0198 }, + { 0xa436, 0xacce }, { 0xa438, 0x90b7 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x01b0 }, { 0xa436, 0xacce }, { 0xa438, 0x98bf }, + { 0xa436, 0xacd0 }, { 0xa438, 0x01b8 }, { 0xa436, 0xacce }, + { 0xa438, 0x9077 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0171 }, + { 0xa436, 0xacce }, { 0xa438, 0x987f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0179 }, { 0xa436, 0xacce }, { 0xa438, 0xfb67 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, { 0xa436, 0xacce }, + { 0xa438, 0xfb6f }, { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, + { 0xa436, 0xacce }, { 0xa438, 0x4087 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0180 }, { 0xa436, 0xacce }, { 0xa438, 0x400f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0108 }, { 0xa436, 0xacce }, + { 0xa438, 0x4807 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0100 }, + { 0xa436, 0xacce }, { 0xa438, 0x488f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0188 }, { 0xa436, 0xacce }, { 0xa438, 0x5027 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0120 }, { 0xa436, 0xacce }, + { 0xa438, 0x502f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0128 }, + { 0xa436, 0xacce }, { 0xa438, 0x5847 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0140 }, { 0xa436, 0xacce }, { 0xa438, 0x584f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0148 }, { 0xa436, 0xacce }, + { 0xa438, 0x60a7 }, { 0xa436, 0xacd0 }, { 0xa438, 0x01a0 }, + { 0xa436, 0xacce }, { 0xa438, 0x68af }, { 0xa436, 0xacd0 }, + { 0xa438, 0x01a8 }, { 0xa436, 0xacce }, { 0xa438, 0x6067 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0161 }, { 0xa436, 0xacce }, + { 0xa438, 0x686f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0169 }, + { 0xa436, 0xacce }, { 0xa438, 0xfb77 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x07ff }, { 0xa436, 0xacce }, { 0xa438, 0xfb7f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, { 0xa436, 0xacce }, + { 0xa438, 0x4017 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0110 }, + { 0xa436, 0xacce }, { 0xa438, 0x401f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0118 }, { 0xa436, 0xacce }, { 0xa438, 0x4837 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0130 }, { 0xa436, 0xacce }, + { 0xa438, 0x483f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0138 }, + { 0xa436, 0xacce }, { 0xa438, 0x5097 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0190 }, { 0xa436, 0xacce }, { 0xa438, 0x505f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0158 }, { 0xa436, 0xacce }, + { 0xa438, 0x5857 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0150 }, + { 0xa436, 0xacce }, { 0xa438, 0x589f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0198 }, { 0xa436, 0xacce }, { 0xa438, 0x70b7 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x01b0 }, { 0xa436, 0xacce }, + { 0xa438, 0x78bf }, { 0xa436, 0xacd0 }, { 0xa438, 0x01b8 }, + { 0xa436, 0xacce }, { 0xa438, 0x7077 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0171 }, { 0xa436, 0xacce }, { 0xa438, 0x787f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0179 }, { 0xa436, 0xacce }, + { 0xa438, 0xfb87 }, { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, + { 0xa436, 0xacce }, { 0xa438, 0xfb8f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x07ff }, { 0xa436, 0xacce }, { 0xa438, 0x40a7 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x01a0 }, { 0xa436, 0xacce }, + { 0xa438, 0x48af }, { 0xa436, 0xacd0 }, { 0xa438, 0x01a8 }, + { 0xa436, 0xacce }, { 0xa438, 0x4067 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0161 }, { 0xa436, 0xacce }, { 0xa438, 0x486f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0169 }, { 0xa436, 0xacce }, + { 0xa438, 0xfb97 }, { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, + { 0xa436, 0xacce }, { 0xa438, 0xfb9f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x07ff }, { 0xa436, 0xacce }, { 0xa438, 0x50b7 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x01b0 }, { 0xa436, 0xacce }, + { 0xa438, 0x58bf }, { 0xa436, 0xacd0 }, { 0xa438, 0x01b8 }, + { 0xa436, 0xacce }, { 0xa438, 0x5077 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0171 }, { 0xa436, 0xacce }, { 0xa438, 0x587f }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0179 }, { 0xa436, 0xacce }, + { 0xa438, 0xfba7 }, { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, + { 0xa436, 0xacce }, { 0xa438, 0xfbaf }, { 0xa436, 0xacd0 }, + { 0xa438, 0x07ff }, { 0xa436, 0xacce }, { 0xa438, 0x2067 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x0161 }, { 0xa436, 0xacce }, + { 0xa438, 0x286f }, { 0xa436, 0xacd0 }, { 0xa438, 0x0169 }, + { 0xa436, 0xacce }, { 0xa438, 0xfbb7 }, { 0xa436, 0xacd0 }, + { 0xa438, 0x07ff }, { 0xa436, 0xacce }, { 0xa438, 0xfbbf }, + { 0xa436, 0xacd0 }, { 0xa438, 0x07ff }, { 0xa436, 0xacce }, + { 0xa438, 0x3077 }, { 0xa436, 0xacd0 }, { 0xa438, 0x0171 }, + { 0xa436, 0xacce }, { 0xa438, 0x387f }, { 0xa436, 0xacd0 }, + { 0xa438, 0x0179 }, { 0xa436, 0xacce }, { 0xa438, 0xfff9 }, + { 0xa436, 0xacd0 }, { 0xa438, 0x17ff }, { 0xa436, 0xacce }, + { 0xa438, 0xfff9 }, { 0xa436, 0xacd0 }, { 0xa438, 0x17ff }, + { 0xa436, 0xacca }, { 0xa438, 0x0004 }, { 0xa436, 0xacc6 }, + { 0xa438, 0x0008 }, { 0xa436, 0xacc8 }, { 0xa438, 0xc000 }, + { 0xa436, 0xacc8 }, { 0xa438, 0x0000 }, { 0xb820, 0x0000 } +}; + static const struct rge_hw_regaddr_array mac_r26_1_mcu[] = { { 0xa436, 0x8023 }, { 0xa438, 0x4700 }, { 0xa436, 0xb82e }, { 0xa438, 0x0001 }, { 0xb820, 0x0090 }, { 0xa436, 0xa016 }, @@ -9614,7 +10248,7 @@ static const struct { MAC_R25_MCU }, mac_r25b_mcu[] = { MAC_R25B_MCU -}, mac_r25d_mcu[] = { +}, mac_r25d_1_mcu[] = { MAC_R25D_MCU }; diff --git a/sys/dev/rge/if_rge_sysctl.c b/sys/dev/rge/if_rge_sysctl.c index a7d6e1572168..75e2316042ea 100644 --- a/sys/dev/rge/if_rge_sysctl.c +++ b/sys/dev/rge/if_rge_sysctl.c @@ -232,6 +232,16 @@ rge_sysctl_attach(struct rge_softc *sc) "debug", CTLFLAG_RW, &sc->sc_debug, 0, "control debugging printfs"); + sc->sc_rx_process_limit = 16; + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "rx_process_limit", CTLFLAG_RW, &sc->sc_rx_process_limit, 0, + "max number of RX packets to process per interrupt"); + + sc->sc_disable_aspm = 0; + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "disable_aspm", CTLFLAG_RDTUN, &sc->sc_disable_aspm, 0, + "disable PCIe ASPM and ECPM (requires reboot)"); + /* Stats */ rge_sysctl_drv_stats_attach(sc); rge_sysctl_mac_stats_attach(sc); diff --git a/sys/dev/rge/if_rgereg.h b/sys/dev/rge/if_rgereg.h index 7b34e3cefbe6..7da8ff42f2b4 100644 --- a/sys/dev/rge/if_rgereg.h +++ b/sys/dev/rge/if_rgereg.h @@ -365,13 +365,17 @@ struct rge_hw_mac_stats { #define RGE_STATS_ALIGNMENT 64 /* Ram version */ -#define RGE_MAC_R25D_RCODE_VER 0x0027 +#define RGE_MAC_R25D_1_RCODE_VER 0x0027 +#define RGE_MAC_R25D_2_RCODE_VER 0x0031 #define RGE_MAC_R26_1_RCODE_VER 0x0033 #define RGE_MAC_R26_2_RCODE_VER 0x0060 #define RGE_MAC_R27_RCODE_VER 0x0036 #define RGE_MAC_R25_RCODE_VER 0x0b33 #define RGE_MAC_R25B_RCODE_VER 0x0b99 +#define RGE_TYPE_R25D(sc) \ + ((sc)->rge_type == MAC_R25D_1 || (sc)->rge_type == MAC_R25D_2) + #define RGE_TYPE_R26(sc) \ ((sc)->rge_type == MAC_R26_1 || (sc)->rge_type == MAC_R26_2) diff --git a/sys/dev/rge/if_rgevar.h b/sys/dev/rge/if_rgevar.h index 504d56cba423..2e80dcf42187 100644 --- a/sys/dev/rge/if_rgevar.h +++ b/sys/dev/rge/if_rgevar.h @@ -30,7 +30,8 @@ enum rge_mac_type { MAC_UNKNOWN = 1, MAC_R25, MAC_R25B, - MAC_R25D, + MAC_R25D_1, + MAC_R25D_2, MAC_R26_1, MAC_R26_2, MAC_R27 @@ -122,7 +123,6 @@ struct rge_rx { int rge_rxq_prodidx; int rge_rxq_considx; -// struct if_rxring rge_rx_ring; bus_addr_t rge_rx_list_paddr; bus_dmamap_t rge_rx_list_map; struct rge_rx_desc *rge_rx_list; @@ -136,7 +136,6 @@ struct rge_queues { void *q_ihc; int q_index; char q_name[16]; -// pci_intr_handle_t q_ih; struct rge_tx q_tx; struct rge_rx q_rx; }; @@ -170,8 +169,6 @@ struct rge_softc { bus_dma_tag_t sc_dmat_rx_buf; bus_dma_tag_t sc_dmat_stats_buf; -// pci_chipset_tag_t sc_pc; -// pcitag_t sc_tag; struct ifmedia sc_media; /* media info */ enum rge_mac_type rge_type; @@ -203,8 +200,13 @@ struct rge_softc { #define RGE_IMTYPE_SIM 1 int sc_watchdog; + int rge_if_flags; + uint32_t sc_debug; + int sc_rx_process_limit; + int sc_disable_aspm; + struct rge_drv_stats sc_drv_stats; struct rge_mac_stats sc_mac_stats; diff --git a/sys/dev/sbni/if_sbni_isa.c b/sys/dev/sbni/if_sbni_isa.c index 113ff3d954e4..9e75629dcb84 100644 --- a/sys/dev/sbni/if_sbni_isa.c +++ b/sys/dev/sbni/if_sbni_isa.c @@ -53,7 +53,7 @@ static device_method_t sbni_isa_methods[] = { /* Device interface */ DEVMETHOD(device_probe, sbni_probe_isa), DEVMETHOD(device_attach, sbni_attach_isa), - { 0, 0 } + DEVMETHOD_END }; static driver_t sbni_isa_driver = { diff --git a/sys/dev/sbni/if_sbni_pci.c b/sys/dev/sbni/if_sbni_pci.c index b1b0614613eb..549618dd1b0e 100644 --- a/sys/dev/sbni/if_sbni_pci.c +++ b/sys/dev/sbni/if_sbni_pci.c @@ -55,7 +55,7 @@ static device_method_t sbni_pci_methods[] = { DEVMETHOD(device_probe, sbni_pci_probe), DEVMETHOD(device_attach, sbni_pci_attach), DEVMETHOD(device_detach, sbni_pci_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t sbni_pci_driver = { diff --git a/sys/dev/scc/scc_bus.h b/sys/dev/scc/scc_bus.h index 96169d7403d8..3b86dabf1046 100644 --- a/sys/dev/scc/scc_bus.h +++ b/sys/dev/scc/scc_bus.h @@ -32,12 +32,14 @@ #include <sys/serial.h> #include <serdev_if.h> -#define SCC_IVAR_CHANNEL 0 -#define SCC_IVAR_CLASS 1 -#define SCC_IVAR_CLOCK 2 -#define SCC_IVAR_MODE 3 -#define SCC_IVAR_REGSHFT 4 -#define SCC_IVAR_HWMTX 5 +enum { + SCC_IVAR_CHANNEL = BUS_IVARS_PRIVATE, + SCC_IVAR_CLASS, + SCC_IVAR_CLOCK, + SCC_IVAR_MODE, + SCC_IVAR_REGSHFT, + SCC_IVAR_HWMTX +}; /* Hardware class -- the SCC type. */ #define SCC_CLASS_UNUSED 0 diff --git a/sys/dev/sdhci/sdhci_fdt_rockchip.c b/sys/dev/sdhci/sdhci_fdt_rockchip.c index 44a5e2ffe271..2d0ade8055e7 100644 --- a/sys/dev/sdhci/sdhci_fdt_rockchip.c +++ b/sys/dev/sdhci/sdhci_fdt_rockchip.c @@ -113,12 +113,10 @@ static struct ofw_compat_data compat_data[] = { static int sdhci_fdt_rockchip_probe(device_t dev) { - struct sdhci_fdt_softc *sc = device_get_softc(dev); - - sc->quirks = 0; - switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) { if (!ofw_bus_status_okay(dev)) return (ENXIO); + + switch (ofw_bus_search_compatible(dev, compat_data)->ocd_data) { case SDHCI_FDT_RK3399: device_set_desc(dev, "Rockchip RK3399 fdt SDHCI controller"); break; @@ -129,7 +127,7 @@ sdhci_fdt_rockchip_probe(device_t dev) return (ENXIO); } - return (0); + return (BUS_PROBE_DEFAULT); } static int diff --git a/sys/dev/sdio/sdio_subr.c b/sys/dev/sdio/sdio_subr.c index f234eb8bdc84..64b1145e2057 100644 --- a/sys/dev/sdio/sdio_subr.c +++ b/sys/dev/sdio/sdio_subr.c @@ -166,6 +166,36 @@ sdio_write_1(struct sdio_func *f, uint32_t addr, uint8_t val, int *err) *err = error; } +uint16_t +sdio_read_2(struct sdio_func *f, uint32_t addr, int *err) +{ + int error; + uint16_t v; + + error = SDIO_READ_EXTENDED(device_get_parent(f->dev), f->fn, addr, + sizeof(v), (uint8_t *)&v, true); + if (error) { + if (err != NULL) + *err = error; + return (0xffff); + } else { + if (err != NULL) + *err = 0; + return (le16toh(v)); + } +} + +void +sdio_write_2(struct sdio_func *f, uint32_t addr, uint16_t val, int *err) +{ + int error; + + error = SDIO_WRITE_EXTENDED(device_get_parent(f->dev), f->fn, addr, + sizeof(val), (uint8_t *)&val, true); + if (err != NULL) + *err = error; +} + uint32_t sdio_read_4(struct sdio_func *f, uint32_t addr, int *err) { diff --git a/sys/dev/sdio/sdio_subr.h b/sys/dev/sdio/sdio_subr.h index 2d2ae9b01230..96df2e7d658a 100644 --- a/sys/dev/sdio/sdio_subr.h +++ b/sys/dev/sdio/sdio_subr.h @@ -95,6 +95,8 @@ int sdio_set_block_size(struct sdio_func *, uint16_t); uint8_t sdio_read_1(struct sdio_func *, uint32_t, int *); void sdio_write_1(struct sdio_func *, uint32_t, uint8_t, int *); +uint16_t sdio_read_2(struct sdio_func *, uint32_t, int *); +void sdio_write_2(struct sdio_func *, uint32_t, uint16_t, int *); uint32_t sdio_read_4(struct sdio_func *, uint32_t, int *); void sdio_write_4(struct sdio_func *, uint32_t, uint32_t, int *); diff --git a/sys/dev/sdio/sdiob.h b/sys/dev/sdio/sdiob.h index 316a23b86103..3875ced43731 100644 --- a/sys/dev/sdio/sdiob.h +++ b/sys/dev/sdio/sdiob.h @@ -64,7 +64,7 @@ #ifdef _SYS_BUS_H_ /* Ivars for sdiob. */ enum sdiob_dev_enum { - SDIOB_IVAR_SUPPORT_MULTIBLK, + SDIOB_IVAR_SUPPORT_MULTIBLK = BUS_IVARS_PRIVATE, SDIOB_IVAR_FUNCTION, SDIOB_IVAR_FUNCNUM, SDIOB_IVAR_CLASS, @@ -73,6 +73,8 @@ enum sdiob_dev_enum { SDIOB_IVAR_DRVDATA, }; +struct sdio_func; + #define SDIOB_ACCESSOR(var, ivar, type) \ __BUS_ACCESSOR(sdio, var, SDIOB, ivar, type) diff --git a/sys/dev/siis/siis.c b/sys/dev/siis/siis.c index 202fc24143b5..50a9ceec3707 100644 --- a/sys/dev/siis/siis.c +++ b/sys/dev/siis/siis.c @@ -433,7 +433,7 @@ static device_method_t siis_methods[] = { DEVMETHOD(bus_teardown_intr,siis_teardown_intr), DEVMETHOD(bus_child_location, siis_child_location), DEVMETHOD(bus_get_dma_tag, siis_get_dma_tag), - { 0, 0 } + DEVMETHOD_END }; static driver_t siis_driver = { @@ -631,7 +631,7 @@ static device_method_t siisch_methods[] = { DEVMETHOD(device_detach, siis_ch_detach), DEVMETHOD(device_suspend, siis_ch_suspend), DEVMETHOD(device_resume, siis_ch_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t siisch_driver = { diff --git a/sys/dev/smartpqi/smartpqi_cam.c b/sys/dev/smartpqi/smartpqi_cam.c index ffdd9fd7da79..690b38c9f855 100644 --- a/sys/dev/smartpqi/smartpqi_cam.c +++ b/sys/dev/smartpqi/smartpqi_cam.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -54,7 +54,7 @@ update_sim_properties(struct cam_sim *sim, struct ccb_pathinq *cpi) cpi->initiator_id = 255; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN-1); cpi->sim_vid[sizeof(cpi->sim_vid)-1] = '\0'; - strncpy(cpi->hba_vid, "Microsemi", HBA_IDLEN-1); + strncpy(cpi->hba_vid, "Microchip", HBA_IDLEN-1); cpi->hba_vid[sizeof(cpi->hba_vid)-1] = '\0'; strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN-1); cpi->dev_name[sizeof(cpi->dev_name)-1] = '\0'; @@ -71,7 +71,6 @@ update_sim_properties(struct cam_sim *sim, struct ccb_pathinq *cpi) cpi->hba_subvendor = pci_get_subvendor(dev); cpi->hba_subdevice = pci_get_subdevice(dev); - DBG_FUNC("OUT\n"); } @@ -154,10 +153,6 @@ os_remove_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) } xpt_async(AC_LOST_DEVICE, tmppath, NULL); xpt_free_path(tmppath); - /* softs->device_list[device->target][device->lun] = NULL; */ - int index = pqisrc_find_device_list_index(softs,device); - if (index >= 0 && index < PQI_MAX_DEVICES) - softs->dev_list[index] = NULL; pqisrc_free_device(softs, device); } @@ -335,7 +330,7 @@ os_io_response_success(rcb_t *rcb) static void copy_sense_data_to_csio(struct ccb_scsiio *csio, - uint8_t *sense_data, uint16_t sense_data_len) + uint8_t const *sense_data, uint16_t sense_data_len) { DBG_IO("IN csio = %p\n", csio); @@ -740,7 +735,7 @@ smartpqi_target_rescan(struct pqisrc_softstate *softs) /* if(softs->device_list[target][lun]){ */ if(softs->dev_list[index] != NULL) { device = softs->dev_list[index]; - DBG_INFO("calling smartpqi_lun_rescan with TL = %d:%d\n",device->target,device->lun); + DBG_INFO("calling smartpqi_lun_rescan with T%d:L%d\n",device->target,device->lun); smartpqi_lun_rescan(softs, device->target, device->lun); } } @@ -821,7 +816,6 @@ pqisrc_io_start(struct cam_sim *sim, union ccb *ccb) if (index == INVALID_ELEM) { ccb->ccb_h.status = CAM_DEV_NOT_THERE; - DBG_INFO("Invalid index/device!!!, Device BTL %u:%d:%d\n", softs->bus_id, target, lun); return ENXIO; } @@ -850,7 +844,7 @@ pqisrc_io_start(struct cam_sim *sim, union ccb *ccb) } /* Check device reset */ if (DEVICE_RESET(dvp)) { - ccb->ccb_h.status = CAM_SCSI_BUSY | CAM_REQ_INPROG | CAM_BUSY; + ccb->ccb_h.status = CAM_BUSY; DBG_WARN("Device %d reset returned busy\n", ccb->ccb_h.target_id); return EBUSY; } @@ -915,7 +909,7 @@ pqisrc_io_start(struct cam_sim *sim, union ccb *ccb) } static inline int -pqi_tmf_status_to_bsd_tmf_status(int pqi_status, rcb_t *rcb) +pqi_tmf_status_to_bsd_tmf_status(int pqi_status, rcb_t const *rcb) { if (PQI_STATUS_SUCCESS == pqi_status && PQI_STATUS_SUCCESS == rcb->status) @@ -931,7 +925,7 @@ static int pqisrc_scsi_abort_task(pqisrc_softstate_t *softs, union ccb *ccb) { rcb_t *rcb = NULL; - struct ccb_hdr *ccb_h = &ccb->ccb_h; + struct ccb_hdr const *ccb_h = &ccb->ccb_h; rcb_t *prcb = ccb->ccb_h.sim_priv.entries[0].ptr; uint32_t tag; int rval; @@ -971,7 +965,7 @@ error_tmf: static int pqisrc_scsi_abort_task_set(pqisrc_softstate_t *softs, union ccb *ccb) { - struct ccb_hdr *ccb_h = &ccb->ccb_h; + struct ccb_hdr const *ccb_h = &ccb->ccb_h; rcb_t *rcb = NULL; uint32_t tag; int rval; @@ -1013,7 +1007,7 @@ pqisrc_target_reset( pqisrc_softstate_t *softs, union ccb *ccb) { /* pqi_scsi_dev_t *devp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; */ - struct ccb_hdr *ccb_h = &ccb->ccb_h; + struct ccb_hdr const *ccb_h = &ccb->ccb_h; rcb_t *rcb = NULL; uint32_t tag; int rval; @@ -1069,7 +1063,7 @@ static void smartpqi_cam_action(struct cam_sim *sim, union ccb *ccb) { struct pqisrc_softstate *softs = cam_sim_softc(sim); - struct ccb_hdr *ccb_h = &ccb->ccb_h; + struct ccb_hdr const *ccb_h = &ccb->ccb_h; DBG_FUNC("IN\n"); @@ -1209,22 +1203,19 @@ smartpqi_async(void *callback_arg, u_int32_t code, } uint32_t t_id = cgd->ccb_h.target_id; - /* if (t_id <= (PQI_CTLR_INDEX - 1)) { */ - if (t_id >= PQI_CTLR_INDEX) { - if (softs != NULL) { - /* pqi_scsi_dev_t *dvp = softs->device_list[t_id][cgd->ccb_h.target_lun]; */ - int lun = cgd->ccb_h.target_lun; - int index = pqisrc_find_btl_list_index(softs,softs->bus_id,t_id,lun); - if (index != INVALID_ELEM) { - pqi_scsi_dev_t *dvp = softs->dev_list[index]; - if (dvp == NULL) { - DBG_ERR("Target is null, target id=%u\n", t_id); - break; - } - smartpqi_adjust_queue_depth(path, dvp->queue_depth); - } - } - } + if (softs != NULL) { + /* pqi_scsi_dev_t *dvp = softs->device_list[t_id][cgd->ccb_h.target_lun]; */ + int lun = cgd->ccb_h.target_lun; + int index = pqisrc_find_btl_list_index(softs,softs->bus_id,t_id,lun); + if (index != INVALID_ELEM) { + pqi_scsi_dev_t const *dvp = softs->dev_list[index]; + if (dvp == NULL) { + DBG_ERR("Target is null, target id=%u\n", t_id); + break; + } + smartpqi_adjust_queue_depth(path, dvp->queue_depth); + } + } break; } default: diff --git a/sys/dev/smartpqi/smartpqi_cmd.c b/sys/dev/smartpqi/smartpqi_cmd.c index 8486ac12df79..b71879aa81f6 100644 --- a/sys/dev/smartpqi/smartpqi_cmd.c +++ b/sys/dev/smartpqi/smartpqi_cmd.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,7 +35,7 @@ pqisrc_submit_cmnd(pqisrc_softstate_t *softs, ib_queue_t *ib_q, void *req) { char *slot = NULL; uint32_t offset; - iu_header_t *hdr = (iu_header_t *)req; + iu_header_t const *hdr = (iu_header_t *)req; /*TODO : Can be fixed a size copying of IU ? */ uint32_t iu_len = hdr->iu_length + 4 ; /* header size */ int i = 0; diff --git a/sys/dev/smartpqi/smartpqi_controllers.h b/sys/dev/smartpqi/smartpqi_controllers.h new file mode 100644 index 000000000000..d5276f01a7e1 --- /dev/null +++ b/sys/dev/smartpqi/smartpqi_controllers.h @@ -0,0 +1,375 @@ +/*- + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Supported controllers + */ +struct pqi_ident +{ + u_int16_t vendor; + u_int16_t device; + u_int16_t subvendor; + u_int16_t subdevice; + int hwif; + char *desc; +} pqi_identifiers[] = { + /* (MSCC PM8205 8x12G based) */ + {0x9005, 0x028f, 0x103c, 0x600, PQI_HWIF_SRCV, "P408i-p SR Gen10"}, + {0x9005, 0x028f, 0x103c, 0x601, PQI_HWIF_SRCV, "P408e-p SR Gen10"}, + {0x9005, 0x028f, 0x103c, 0x602, PQI_HWIF_SRCV, "P408i-a SR Gen10"}, + {0x9005, 0x028f, 0x103c, 0x603, PQI_HWIF_SRCV, "P408i-c SR Gen10"}, + {0x9005, 0x028f, 0x1028, 0x1FE0, PQI_HWIF_SRCV, "SmartRAID 3162-8i/eDell"}, + {0x9005, 0x028f, 0x9005, 0x608, PQI_HWIF_SRCV, "SmartRAID 3162-8i/e"}, + {0x9005, 0x028f, 0x103c, 0x609, PQI_HWIF_SRCV, "P408i-sb SR G10"}, + + /* (MSCC PM8225 8x12G based) */ + {0x9005, 0x028f, 0x103c, 0x650, PQI_HWIF_SRCV, "E208i-p SR Gen10"}, + {0x9005, 0x028f, 0x103c, 0x651, PQI_HWIF_SRCV, "E208e-p SR Gen10"}, + {0x9005, 0x028f, 0x103c, 0x652, PQI_HWIF_SRCV, "E208i-c SR Gen10"}, + {0x9005, 0x028f, 0x103c, 0x654, PQI_HWIF_SRCV, "E208i-a SR Gen10"}, + {0x9005, 0x028f, 0x103c, 0x655, PQI_HWIF_SRCV, "P408e-m SR Gen10"}, + {0x9005, 0x028f, 0x9005, 0x659, PQI_HWIF_SRCV, "2100C8iOXS"}, + + /* (MSCC PM8221 8x12G based) */ + {0x9005, 0x028f, 0x103c, 0x700, PQI_HWIF_SRCV, "P204i-c SR Gen10"}, + {0x9005, 0x028f, 0x103c, 0x701, PQI_HWIF_SRCV, "P204i-b SR Gen10"}, + {0x9005, 0x028f, 0x193d, 0x1104, PQI_HWIF_SRCV, "UN RAID P2404-Mf-4i-2GB"}, + {0x9005, 0x028f, 0x193d, 0x1106, PQI_HWIF_SRCV, "UN RAID P2404-Mf-4i-1GB"}, + {0x9005, 0x028f, 0x193d, 0x1108, PQI_HWIF_SRCV, "UN RAID P4408-Ma-8i-2GB"}, + {0x9005, 0x028f, 0x193d, 0x1109, PQI_HWIF_SRCV, "UN RAID P4408-Mr-8i-2GB"}, + + /* (MSCC PM8204 8x12G based) */ + {0x9005, 0x028f, 0x9005, 0x800, PQI_HWIF_SRCV, "SmartRAID 3154-8i"}, + {0x9005, 0x028f, 0x9005, 0x801, PQI_HWIF_SRCV, "SmartRAID 3152-8i"}, + {0x9005, 0x028f, 0x9005, 0x802, PQI_HWIF_SRCV, "SmartRAID 3151-4i"}, + {0x9005, 0x028f, 0x9005, 0x803, PQI_HWIF_SRCV, "SmartRAID 3101-4i"}, + {0x9005, 0x028f, 0x9005, 0x804, PQI_HWIF_SRCV, "SmartRAID 3154-8e"}, + {0x9005, 0x028f, 0x9005, 0x805, PQI_HWIF_SRCV, "SmartRAID 3102-8i"}, + {0x9005, 0x028f, 0x9005, 0x806, PQI_HWIF_SRCV, "SmartRAID 3100"}, + {0x9005, 0x028f, 0x9005, 0x807, PQI_HWIF_SRCV, "SmartRAID 3162-8i"}, + {0x9005, 0x028f, 0x152d, 0x8a22, PQI_HWIF_SRCV, "QS-8204-8i"}, + {0x9005, 0x028f, 0x193d, 0xf460, PQI_HWIF_SRCV, "UN RAID P460-M4"}, + {0x9005, 0x028f, 0x193d, 0xf461, PQI_HWIF_SRCV, "UN RAID P460-B4"}, + {0x9005, 0x028f, 0x1bd4, 0x004b, PQI_HWIF_SRCV, "PM8204-2GB"}, + {0x9005, 0x028f, 0x1bd4, 0x004c, PQI_HWIF_SRCV, "PM8204-4GB"}, + {0x9005, 0x028f, 0x1ff9, 0x004b, PQI_HWIF_SRCV, "RAID PM8204-2GB"}, + {0x9005, 0x028f, 0x1ff9, 0x004c, PQI_HWIF_SRCV, "RAID PM8204-4GB"}, + {0x9005, 0x028f, 0x193d, 0x0462, PQI_HWIF_SRCV, "UN RAID P460-Mr1-8i-4GB"}, + {0x9005, 0x028f, 0x193d, 0x1105, PQI_HWIF_SRCV, "UN RAID P4408-Mf-8i-2GB"}, + {0x9005, 0x028f, 0x193d, 0x1107, PQI_HWIF_SRCV, "UN RAID P4408-Mf-8i-4GB"}, + {0x9005, 0x028f, 0x193d, 0x1110, PQI_HWIF_SRCV, "UN RAID P4408-Mr-2"}, + {0x9005, 0x028f, 0x1d8d, 0x800, PQI_HWIF_SRCV, "Fiberhome SmartRAID AIS-8204-8i"}, + {0x9005, 0x028f, 0x9005, 0x0808, PQI_HWIF_SRCV, "SmartRAID 3101E-4i"}, + {0x9005, 0x028f, 0x9005, 0x0809, PQI_HWIF_SRCV, "SmartRAID 3102E-8i"}, + {0x9005, 0x028f, 0x9005, 0x080a, PQI_HWIF_SRCV, "SmartRAID 3152-8i/N"}, + {0x9005, 0x028f, 0x1cc4, 0x0101, PQI_HWIF_SRCV, "Ramaxel FBGF-RAD PM8204"}, + {0x9005, 0x028f, 0x1f3a, 0x0104, PQI_HWIF_SRCV, "PL SmartROC PM8204"}, + {0x9005, 0x028f, 0x1f51, 0x1043, PQI_HWIF_SRCV, "SmartRAID P7502-8i"}, + {0x9005, 0x028f, 0x1f51, 0x1045, PQI_HWIF_SRCV, "SmartRAID P7504-8i"}, + {0x9005, 0x028f, 0x1f51, 0x1011, PQI_HWIF_SRCV, "SmartRAID P7504N-8i"}, + {0x9005, 0x028f, 0x207d, 0x4140, PQI_HWIF_SRCV, "HRDT TrustRAID D3152s-8i"}, + {0x9005, 0x028f, 0x207d, 0x4240, PQI_HWIF_SRCV, "HRDT TrustRAID D3154s-8i"}, + + /* (MSCC PM8222 8x12G based) */ + {0x9005, 0x028f, 0x9005, 0x900, PQI_HWIF_SRCV, "SmartHBA 2100-8i"}, + {0x9005, 0x028f, 0x9005, 0x901, PQI_HWIF_SRCV, "SmartHBA 2100-4i"}, + {0x9005, 0x028f, 0x9005, 0x902, PQI_HWIF_SRCV, "HBA 1100-8i"}, + {0x9005, 0x028f, 0x9005, 0x903, PQI_HWIF_SRCV, "HBA 1100-4i"}, + {0x9005, 0x028f, 0x9005, 0x904, PQI_HWIF_SRCV, "SmartHBA 2100-8e"}, + {0x9005, 0x028f, 0x9005, 0x905, PQI_HWIF_SRCV, "HBA 1100-8e"}, + {0x9005, 0x028f, 0x9005, 0x906, PQI_HWIF_SRCV, "SmartHBA 2100-4i4e"}, + {0x9005, 0x028f, 0x9005, 0x907, PQI_HWIF_SRCV, "HBA 1100"}, + {0x9005, 0x028f, 0x9005, 0x908, PQI_HWIF_SRCV, "SmartHBA 2100"}, + {0x9005, 0x028f, 0x9005, 0x90a, PQI_HWIF_SRCV, "SmartHBA 2100A-8i"}, + {0x9005, 0x028f, 0x193d, 0x8460, PQI_HWIF_SRCV, "UN HBA H460-M1"}, + {0x9005, 0x028f, 0x193d, 0x8461, PQI_HWIF_SRCV, "UN HBA H460-B1"}, + {0x9005, 0x028f, 0x193d, 0x8462, PQI_HWIF_SRCV, "UN HBA H460-Mr1-8i"}, + {0x9005, 0x028f, 0x193d, 0xc460, PQI_HWIF_SRCV, "UN RAID P460-M2"}, + {0x9005, 0x028f, 0x193d, 0xc461, PQI_HWIF_SRCV, "UN RAID P460-B2"}, + {0x9005, 0x028f, 0x1bd4, 0x004a, PQI_HWIF_SRCV, "PM8222-SHBA"}, + {0x9005, 0x028f, 0x1ff9, 0x004a, PQI_HWIF_SRCV, "PM8222-SHBA"}, + {0x9005, 0x028f, 0x13fe, 0x8312, PQI_HWIF_SRCV, "MIC-8312BridgeB"}, + {0x9005, 0x028f, 0x1bd4, 0x004f, PQI_HWIF_SRCV, "PM8222-HBA"}, + {0x9005, 0x028f, 0x1ff9, 0x004f, PQI_HWIF_SRCV, "PM8222-HBA"}, + {0x9005, 0x028f, 0x1d8d, 0x908, PQI_HWIF_SRCV, "Fiberhome SmartHBA AIS-8222-8i"}, + {0x9005, 0x028f, 0x1bd4, 0x006C, PQI_HWIF_SRCV, "RS0800M5E8i"}, + {0x9005, 0x028f, 0x1bd4, 0x006D, PQI_HWIF_SRCV, "RS0800M5H8i"}, + {0x9005, 0x028f, 0x1ff9, 0x006C, PQI_HWIF_SRCV, "RS0800M5E8i"}, + {0x9005, 0x028f, 0x1ff9, 0x006D, PQI_HWIF_SRCV, "RS0800M5H8i"}, + {0x9005, 0x028f, 0x1cc4, 0x0201, PQI_HWIF_SRCV, "Ramaxel FBGF-RAD PM8222"}, + {0x9005, 0x028f, 0x1f51, 0x1044, PQI_HWIF_SRCV, "SmartHBA P6500-8i"}, + {0x9005, 0x028f, 0x1f3f, 0x0610, PQI_HWIF_SRCV, "3SNIC SSSRAID 3S610"}, + {0x9005, 0x028f, 0x207d, 0x4840, PQI_HWIF_SRCV, "HRDT TrustHBA H3100s-8i"}, + {0x9005, 0x028f, 0x207d, 0x4940, PQI_HWIF_SRCV, "HRDT TrustRAID D3102s-8i"}, + + /* (SRCx MSCC FVB 24x12G based) */ + {0x9005, 0x028f, 0x103c, 0x1001, PQI_HWIF_SRCV, "MSCC FVB"}, + + /* (MSCC PM8241 24x12G based) */ + + /* (MSCC PM8242 24x12G based) */ + {0x9005, 0x028f, 0x152d, 0x8a37, PQI_HWIF_SRCV, "QS-8242-24i"}, + {0x9005, 0x028f, 0x9005, 0x1300, PQI_HWIF_SRCV, "HBA 1100-8i8e"}, + {0x9005, 0x028f, 0x9005, 0x1301, PQI_HWIF_SRCV, "HBA 1100-24i"}, + {0x9005, 0x028f, 0x9005, 0x1302, PQI_HWIF_SRCV, "SmartHBA 2100-8i8e"}, + {0x9005, 0x028f, 0x9005, 0x1303, PQI_HWIF_SRCV, "SmartHBA 2100-24i"}, + {0x9005, 0x028f, 0x105b, 0x1321, PQI_HWIF_SRCV, "8242-24i"}, + {0x9005, 0x028f, 0x1bd4, 0x0045, PQI_HWIF_SRCV, "SMART-HBA 8242-24i"}, + {0x9005, 0x028f, 0x1ff9, 0x0045, PQI_HWIF_SRCV, "SMART-HBA 8242-24i"}, + {0x9005, 0x028f, 0x1bd4, 0x006B, PQI_HWIF_SRCV, "RS0800M5H24i"}, + {0x9005, 0x028f, 0x1bd4, 0x0070, PQI_HWIF_SRCV, "RS0800M5E24i"}, + {0x9005, 0x028f, 0x1ff9, 0x006B, PQI_HWIF_SRCV, "RS0800M5H24i"}, + {0x9005, 0x028f, 0x1ff9, 0x0070, PQI_HWIF_SRCV, "RS0800M5E24i"}, + + /* (MSCC PM8236 16x12G based) */ + {0x9005, 0x028f, 0x152d, 0x8a24, PQI_HWIF_SRCV, "QS-8236-16i"}, + {0x9005, 0x028f, 0x9005, 0x1380, PQI_HWIF_SRCV, "SmartRAID 3154-16i"}, + {0x9005, 0x028f, 0x1bd4, 0x0046, PQI_HWIF_SRCV, "RAID 8236-16i"}, + {0x9005, 0x028f, 0x1ff9, 0x0046, PQI_HWIF_SRCV, "RAID 8236-16i"}, + {0x9005, 0x028f, 0x1d8d, 0x806, PQI_HWIF_SRCV, "Fiberhome SmartRAID AIS-8236-16i"}, + {0x9005, 0x028f, 0x1cf2, 0x0B27, PQI_HWIF_SRCV, "ZTE SmartROC3100 SDPSA/B-18i 4G"}, + {0x9005, 0x028f, 0x1cf2, 0x0B45, PQI_HWIF_SRCV, "ZTE SmartROC3100 SDPSA/B_L-18i 2G"}, + {0x9005, 0x028f, 0x1cf2, 0x5445, PQI_HWIF_SRCV, "ZTE SmartROC3100 RM241-18i 2G"}, + {0x9005, 0x028f, 0x1cf2, 0x544D, PQI_HWIF_SRCV, "ZTE SmartROC3100 RM241B-18i 2G"}, + {0x9005, 0x028f, 0x1cf2, 0x5446, PQI_HWIF_SRCV, "ZTE SmartROC3100 RM242-18i 4G"}, + {0x9005, 0x028f, 0x1cf2, 0x544E, PQI_HWIF_SRCV, "ZTE SmartROC3100 RM242B-18i 4G"}, + {0x9005, 0x028f, 0x1cf2, 0x5451, PQI_HWIF_SRCV, "ZTE SmartROC3100 RS231-8i 2G"}, + {0x9005, 0x028f, 0x1cf2, 0x5452, PQI_HWIF_SRCV, "ZTE SmartROC3100 RS232-8i 4G"}, + {0x9005, 0x028f, 0x1cf2, 0x5449, PQI_HWIF_SRCV, "ZTE SmartROC3100 RS241-18i 2G"}, + {0x9005, 0x028f, 0x1cf2, 0x544A, PQI_HWIF_SRCV, "ZTE SmartROC3100 RS242-18i 4G"}, + {0x9005, 0x028f, 0x1bd4, 0x006F, PQI_HWIF_SRCV, "RS0804M5R16i"}, + {0x9005, 0x028f, 0x1ff9, 0x006F, PQI_HWIF_SRCV, "RS0804M5R16i"}, + {0x9005, 0x028f, 0x1f51, 0x1010, PQI_HWIF_SRCV, "SmartRAID P7504N-16i"}, + + + + /* (MSCC PM8237 24x12G based) */ + {0x9005, 0x028f, 0x103c, 0x1100, PQI_HWIF_SRCV, "P816i-a SR Gen10"}, + {0x9005, 0x028f, 0x103c, 0x1101, PQI_HWIF_SRCV, "P416ie-m SR G10"}, + + /* (MSCC PM8238 16x12G based) */ + {0x9005, 0x028f, 0x152d, 0x8a23, PQI_HWIF_SRCV, "QS-8238-16i"}, + {0x9005, 0x028f, 0x9005, 0x1280, PQI_HWIF_SRCV, "HBA 1100-16i"}, + {0x9005, 0x028f, 0x9005, 0x1281, PQI_HWIF_SRCV, "HBA 1100-16e"}, + {0x9005, 0x028f, 0x105b, 0x1211, PQI_HWIF_SRCV, "8238-16i"}, + {0x9005, 0x028f, 0x1bd4, 0x0048, PQI_HWIF_SRCV, "SMART-HBA 8238-16i"}, + {0x9005, 0x028f, 0x1ff9, 0x0048, PQI_HWIF_SRCV, "SMART-HBA 8238-16i"}, + {0x9005, 0x028f, 0x9005, 0x1282, PQI_HWIF_SRCV, "SmartHBA 2100-16i"}, + {0x9005, 0x028f, 0x1d8d, 0x916, PQI_HWIF_SRCV, "Fiberhome SmartHBA AIS-8238-16i"}, + {0x9005, 0x028f, 0x1458, 0x1000, PQI_HWIF_SRCV, "GIGABYTE SmartHBA CLN1832"}, + {0x9005, 0x028f, 0x1cf2, 0x0B29, PQI_HWIF_SRCV, "ZTE SmartIOC2100 SDPSA/B_I-18i"}, + {0x9005, 0x028f, 0x1cf2, 0x5447, PQI_HWIF_SRCV, "ZTE SmartIOC2100 RM243-18i"}, + {0x9005, 0x028f, 0x1cf2, 0x5453, PQI_HWIF_SRCV, "ZTE SmartIOC2100 RS233-8i"}, + {0x9005, 0x028f, 0x1cf2, 0x544B, PQI_HWIF_SRCV, "ZTE SmartIOC2100 RS243-18i"}, + {0x9005, 0x028f, 0x1cf2, 0x544F, PQI_HWIF_SRCV, "ZTE SmartIOC2100 RM243B-18i"}, + {0x9005, 0x028f, 0x1bd4, 0x0071, PQI_HWIF_SRCV, "RS0800M5H16i"}, + {0x9005, 0x028f, 0x1bd4, 0x0072, PQI_HWIF_SRCV, "RS0800M5E16i"}, + {0x9005, 0x028f, 0x1ff9, 0x0071, PQI_HWIF_SRCV, "RS0800M5H16i"}, + {0x9005, 0x028f, 0x1ff9, 0x0072, PQI_HWIF_SRCV, "RS0800M5E16i"}, + {0x9005, 0x028f, 0x1018, 0x8238, PQI_HWIF_SRCV, "Ramaxel SmartHBA RX8238-16i"}, + + /* (MSCC PM8240 24x12G based) */ + {0x9005, 0x028f, 0x152d, 0x8a36, PQI_HWIF_SRCV, "QS-8240-24i"}, + {0x9005, 0x028f, 0x9005, 0x1200, PQI_HWIF_SRCV, "SmartRAID 3154-24i"}, + {0x9005, 0x028f, 0x9005, 0x1201, PQI_HWIF_SRCV, "SmartRAID 3154-8i16e"}, + {0x9005, 0x028f, 0x9005, 0x1202, PQI_HWIF_SRCV, "SmartRAID 3154-8i8e"}, + {0x9005, 0x028f, 0x1bd4, 0x0047, PQI_HWIF_SRCV, "RAID 8240-24i"}, + {0x9005, 0x028f, 0x1ff9, 0x0047, PQI_HWIF_SRCV, "RAID 8240-24i"}, + {0x9005, 0x028f, 0x1dfc, 0x3161, PQI_HWIF_SRCV, "NTCOM SAS3 RAID-24i"}, + {0x9005, 0x028f, 0x1F0C, 0x3161, PQI_HWIF_SRCV, "NT RAID 3100-24i"}, + + /* Huawei ID's */ + {0x9005, 0x028f, 0x19e5, 0xd227, PQI_HWIF_SRCV, "SR465C-M 4G"}, + {0x9005, 0x028f, 0x19e5, 0xd22a, PQI_HWIF_SRCV, "SR765-M"}, + {0x9005, 0x028f, 0x19e5, 0xd228, PQI_HWIF_SRCV, "SR455C-M 2G"}, + {0x9005, 0x028f, 0x19e5, 0xd22c, PQI_HWIF_SRCV, "SR455C-M 4G"}, + {0x9005, 0x028f, 0x19e5, 0xd229, PQI_HWIF_SRCV, "SR155-M"}, + {0x9005, 0x028f, 0x19e5, 0xd22b, PQI_HWIF_SRCV, "SR455C-ME 4G"}, + + /* (MSCC PM8252 8x12G based) */ + {0x9005, 0x028f, 0x193d, 0x110b, PQI_HWIF_SRCV, "UN HBA H4508-Mf-8i"}, + {0x9005, 0x028f, 0x1bd4, 0x0052, PQI_HWIF_SRCV, "MT0801M6E"}, + {0x9005, 0x028f, 0x1bd4, 0x0054, PQI_HWIF_SRCV, "MT0800M6H"}, + {0x9005, 0x028f, 0x1bd4, 0x0086, PQI_HWIF_SRCV, "RT0800M7E"}, + {0x9005, 0x028f, 0x1bd4, 0x0087, PQI_HWIF_SRCV, "RT0800M7H"}, + {0x9005, 0x028f, 0x1ff9, 0x0052, PQI_HWIF_SRCV, "MT0801M6E"}, + {0x9005, 0x028f, 0x1ff9, 0x0054, PQI_HWIF_SRCV, "MT0800M6H"}, + {0x9005, 0x028f, 0x1BD4, 0x00a3, PQI_HWIF_SRCV, "RT0800M6E2i"}, + {0x9005, 0x028f, 0x1ff9, 0x00a3, PQI_HWIF_SRCV, "RT0800M6E2i"}, + {0x9005, 0x028f, 0x1ff9, 0x0086, PQI_HWIF_SRCV, "RT0800M7E"}, + {0x9005, 0x028f, 0x1ff9, 0x0087, PQI_HWIF_SRCV, "RT0800M7H"}, + {0x9005, 0x028f, 0x1f51, 0x1001, PQI_HWIF_SRCV, "SmartHBA P6600-8i"}, + {0x9005, 0x028f, 0x1f51, 0x1003, PQI_HWIF_SRCV, "SmartHBA P6600-8e"}, + {0x9005, 0x028f, 0x9005, 0x1460, PQI_HWIF_SRCV, "HBA 1200"}, + {0x9005, 0x028f, 0x9005, 0x1461, PQI_HWIF_SRCV, "SmartHBA 2200"}, + {0x9005, 0x028f, 0x9005, 0x1462, PQI_HWIF_SRCV, "HBA 1200-8i"}, + {0x9005, 0x028f, 0x1d49, 0x0222, PQI_HWIF_SRCV, "4450-8i HBA"}, + {0x9005, 0x028f, 0x207d, 0x4044, PQI_HWIF_SRCV, "HRDT TrustHBA H4100-8i"}, + {0x9005, 0x028f, 0x207d, 0x4054, PQI_HWIF_SRCV, "HRDT TrustHBA H4100-8e"}, + + /* (MSCC PM8254 32x12G based) */ + {0x9005, 0x028f, 0x1bd4, 0x0051, PQI_HWIF_SRCV, "MT0804M6R"}, + {0x9005, 0x028f, 0x1bd4, 0x0053, PQI_HWIF_SRCV, "MT0808M6R"}, + {0x9005, 0x028f, 0x1bd4, 0x0088, PQI_HWIF_SRCV, "RT0804M7R"}, + {0x9005, 0x028f, 0x1bd4, 0x0089, PQI_HWIF_SRCV, "RT0808M7R"}, + {0x9005, 0x028f, 0x1ff9, 0x0051, PQI_HWIF_SRCV, "MT0804M6R"}, + {0x9005, 0x028f, 0x1ff9, 0x0053, PQI_HWIF_SRCV, "MT0808M6R"}, + {0x9005, 0x028f, 0x1ff9, 0x0088, PQI_HWIF_SRCV, "RT0804M7R"}, + {0x9005, 0x028f, 0x1ff9, 0x0089, PQI_HWIF_SRCV, "RT0808M7R"}, + {0x9005, 0x028f, 0x1f51, 0x1002, PQI_HWIF_SRCV, "SmartRAID P7604-8i"}, + {0x9005, 0x028f, 0x1f51, 0x1004, PQI_HWIF_SRCV, "SmartRAID P7604-8e"}, + {0x9005, 0x028f, 0x1f51, 0x100f, PQI_HWIF_SRCV, "SmartRAID P7604N-8i"}, + {0x9005, 0x028f, 0x9005, 0x14a0, PQI_HWIF_SRCV, "SmartRAID 3254-8i"}, + {0x9005, 0x028f, 0x9005, 0x14a1, PQI_HWIF_SRCV, "SmartRAID 3204-8i"}, + {0x9005, 0x028f, 0x9005, 0x14a2, PQI_HWIF_SRCV, "SmartRAID 3252-8i"}, + {0x9005, 0x028f, 0x9005, 0x14a4, PQI_HWIF_SRCV, "SmartRAID 3254-8i /e"}, + {0x9005, 0x028f, 0x9005, 0x14a5, PQI_HWIF_SRCV, "SmartRAID 3252-8i /e"}, + {0x9005, 0x028f, 0x9005, 0x14a6, PQI_HWIF_SRCV, "SmartRAID 3204-8i /e"}, + {0x9005, 0x028f, 0x1d49, 0x0624, PQI_HWIF_SRCV, "9450-8i 4GB Flash"}, + + /* (MSCC PM8262 16x12G based) */ + {0x9005, 0x028f, 0x9005, 0x14c0, PQI_HWIF_SRCV, "SmartHBA 2200-16i"}, + {0x9005, 0x028f, 0x9005, 0x14c1, PQI_HWIF_SRCV, "HBA 1200-16i"}, + {0x9005, 0x028f, 0x9005, 0x14c3, PQI_HWIF_SRCV, "HBA 1200-16e"}, + {0x9005, 0x028f, 0x9005, 0x14c4, PQI_HWIF_SRCV, "HBA 1200-8e"}, + {0x9005, 0x028f, 0x1f51, 0x1005, PQI_HWIF_SRCV, "SmartHBA P6600-16i"}, + {0x9005, 0x028f, 0x1f51, 0x1007, PQI_HWIF_SRCV, "SmartHBA P6600-8i8e"}, + {0x9005, 0x028f, 0x1f51, 0x1009, PQI_HWIF_SRCV, "SmartHBA P6600-16e"}, + {0x9005, 0x028f, 0x1cf2, 0x54dc, PQI_HWIF_SRCV, "ZTE SmartIOC2200 RM346-16i"}, + {0x9005, 0x028f, 0x1cf2, 0x0806, PQI_HWIF_SRCV, "ZTE SmartIOC2200 RS346-16i"}, + {0x9005, 0x028f, 0x1d49, 0x0223, PQI_HWIF_SRCV, "4450-16i HBA"}, + {0x9005, 0x028f, 0x1d49, 0x0224, PQI_HWIF_SRCV, "4450-8e HBA"}, + {0x9005, 0x028f, 0x1d49, 0x0225, PQI_HWIF_SRCV, "4450-16e HBA"}, + {0x9005, 0x028f, 0x1d49, 0x0521, PQI_HWIF_SRCV, "5450-16i"}, + {0x9005, 0x028f, 0x207d, 0x4084, PQI_HWIF_SRCV, "HRDT TrustHBA H4100-16i"}, + {0x9005, 0x028f, 0x207d, 0x4094, PQI_HWIF_SRCV, "HRDT TrustHBA H4100-16e"}, + + /* (MSCC PM8264 16x12G based) */ + {0x9005, 0x028f, 0x9005, 0x14b0, PQI_HWIF_SRCV, "SmartRAID 3254-16i"}, + {0x9005, 0x028f, 0x9005, 0x14b1, PQI_HWIF_SRCV, "SmartRAID 3258-16i"}, + {0x9005, 0x028f, 0x1f51, 0x1006, PQI_HWIF_SRCV, "SmartRAID P7608-16i"}, + {0x9005, 0x028f, 0x1f51, 0x1008, PQI_HWIF_SRCV, "SmartRAID P7608-8i8e"}, + {0x9005, 0x028f, 0x1f51, 0x100a, PQI_HWIF_SRCV, "SmartRAID P7608-16e"}, + {0x9005, 0x028f, 0x1cf2, 0x54da, PQI_HWIF_SRCV, "ZTE SmartROC3200 RM344-16i 4G"}, + {0x9005, 0x028f, 0x1cf2, 0x54db, PQI_HWIF_SRCV, "ZTE SmartROC3200 RM345-16i 8G"}, + {0x9005, 0x028f, 0x1cf2, 0x0804, PQI_HWIF_SRCV, "ZTE SmartROC3200 RS344-16i 4G"}, + {0x9005, 0x028f, 0x1cf2, 0x0805, PQI_HWIF_SRCV, "ZTE SmartROC3200 RS345-16i 8G"}, + {0x9005, 0x028f, 0x1f51, 0x100e, PQI_HWIF_SRCV, "SmartRAID P7604N-16i"}, + {0x9005, 0x028f, 0x1d49, 0x0625, PQI_HWIF_SRCV, "9450-16i 4GB Flash"}, + {0x9005, 0x028f, 0x1d49, 0x0626, PQI_HWIF_SRCV, "9450-16i 8GB Flash"}, + + /* (MSCC PM8265 16x12G based) */ + {0x9005, 0x028f, 0x1590, 0x02dc, PQI_HWIF_SRCV, "SR416i-a Gen10+"}, + {0x9005, 0x028f, 0x9005, 0x1470, PQI_HWIF_SRCV, "SmartRAID 3200"}, + {0x9005, 0x028f, 0x9005, 0x1471, PQI_HWIF_SRCV, "SmartRAID 3254-16i /e"}, + {0x9005, 0x028f, 0x9005, 0x1472, PQI_HWIF_SRCV, "SmartRAID 3258-16i /e"}, + {0x9005, 0x028f, 0x9005, 0x1473, PQI_HWIF_SRCV, "SmartRAID 3284-16io /e/uC"}, + {0x9005, 0x028f, 0x9005, 0x1474, PQI_HWIF_SRCV, "SmartRAID 3254-16io /e"}, + {0x9005, 0x028f, 0x9005, 0x1475, PQI_HWIF_SRCV, "SmartRAID 3254-16e /e"}, + + /* (MSCC PM8266 16x12G based) */ + {0x9005, 0x028f, 0x1014, 0x0718, PQI_HWIF_SRCV, "IBM 4-Port 24G SAS"}, + {0x9005, 0x028f, 0x9005, 0x1490, PQI_HWIF_SRCV, "HBA 1200p Ultra"}, + {0x9005, 0x028f, 0x9005, 0x1491, PQI_HWIF_SRCV, "SmartHBA 2200p Ultra"}, + {0x9005, 0x028f, 0x9005, 0x1402, PQI_HWIF_SRCV, "HBA Ultra 1200P-16i"}, + {0x9005, 0x028f, 0x9005, 0x1441, PQI_HWIF_SRCV, "HBA Ultra 1200P-32i"}, + {0x9005, 0x028f, 0x1137, 0x0300, PQI_HWIF_SRCV, "Cisco 24G TriMode M1 HBA LFF 32D UCSC-HBAMP1LL32"}, + + /* (MSCC PM8268 16x12G based) */ + {0x9005, 0x028f, 0x9005, 0x14d0, PQI_HWIF_SRCV, "SmartRAID Ultra 3258P-16i"}, + + /* (MSCC PM8269 16x12G based) */ + {0x9005, 0x028f, 0x9005, 0x1400, PQI_HWIF_SRCV, "SmartRAID Ultra 3258P-16i /e"}, + {0x9005, 0x028f, 0x1ff9, 0x00a1, PQI_HWIF_SRCV, "RT1608M6R16i"}, + + /* (MSCC PM8270 16x12G based) */ + {0x9005, 0x028f, 0x9005, 0x1410, PQI_HWIF_SRCV, "HBA Ultra 1200P-16e"}, + {0x9005, 0x028f, 0x9005, 0x1411, PQI_HWIF_SRCV, "HBA 1200 Ultra"}, + {0x9005, 0x028f, 0x9005, 0x1412, PQI_HWIF_SRCV, "SmartHBA 2200 Ultra"}, + {0x9005, 0x028f, 0x9005, 0x1463, PQI_HWIF_SRCV, "SmartHBA 2200-8io /e"}, + {0x9005, 0x028f, 0x9005, 0x14c2, PQI_HWIF_SRCV, "SmartHBA 2200-16io /e"}, + {0x9005, 0x028f, 0x1337, 0x02fa, PQI_HWIF_SRCV, "Cisco 24G TriMode M1 HBA 16D UCSC-HBA-M1L16"}, + + /* (MSCC PM8271 16x12G based) */ + {0x9005, 0x028f, 0x9005, 0x14e0, PQI_HWIF_SRCV, "SmartIOC PM8271"}, + + /* (MSCC PM8272 16x12G based) */ + {0x9005, 0x028f, 0x9005, 0x1420, PQI_HWIF_SRCV, "SmartRAID Ultra 3254-16e"}, + {0x9005, 0x028f, 0x1d49, 0x0628, PQI_HWIF_SRCV, "9450-16e 4GB Flash"}, + + /* (MSCC PM8273 16x12G based) */ + {0x9005, 0x028f, 0x9005, 0x1430, PQI_HWIF_SRCV, "SmartRAID Ultra 3254-16e /e"}, + {0x9005, 0x028f, 0x1137, 0x02f9, PQI_HWIF_SRCV, "Cisco 24G TriMode M1 RAID 4GB FBWC 16D UCSC-RAID-M1L16"}, + {0x9005, 0x028f, 0x1137, 0x02ff, PQI_HWIF_SRCV, "Cisco 24G TriMode M1 RAID 4GB FBWC 6D UCSX-RAID-M1L6"}, + + /* (MSCC PM8274 16x12G based) */ + {0x9005, 0x028f, 0x1e93, 0x1000, PQI_HWIF_SRCV, "ByteHBA JGH43024-8"}, + {0x9005, 0x028f, 0x1e93, 0x1001, PQI_HWIF_SRCV, "ByteHBA JGH43034-8"}, + {0x9005, 0x028f, 0x1e93, 0x1005, PQI_HWIF_SRCV, "ByteHBA JGH43014-8"}, + {0x9005, 0x028f, 0x1f51, 0x100B, PQI_HWIF_SRCV, "SmartHBA P6600-24i"}, + + /* (MSCC PM8275 16x12G based) */ + {0x9005, 0x028f, 0x9005, 0x14f0, PQI_HWIF_SRCV, "SmartIOC PM8275"}, + + /* (MSCC PM8276 16x12G based) */ + {0x9005, 0x028f, 0x9005, 0x1480, PQI_HWIF_SRCV, "SmartRAID 3200 Ultra"}, + {0x9005, 0x028f, 0x1e93, 0x1002, PQI_HWIF_SRCV, "ByteHBA JGH44014-8"}, + + /* (MSCC PM8277 16x12G based) */ + {0x9005, 0x028f, 0x1137, 0x02f8, PQI_HWIF_SRCV, "Cisco 24G TriMode M1 RAID 4GB FBWC 32D UCSC-RAID-MP1L32"}, + + /* (MSCC PM8278 16x12G based) */ + {0x9005, 0x028f, 0x9005, 0x1440, PQI_HWIF_SRCV, "SmartRAID Ultra 3258P-32i"}, + {0x9005, 0x028f, 0x1d49, 0x0627, PQI_HWIF_SRCV, "9450-32i 8GB Flash"}, + + /* (MSCC PM8279 32x12G based) */ + {0x9005, 0x028f, 0x9005, 0x1450, PQI_HWIF_SRCV, "SmartRAID Ultra 3258P-32i /e"}, + {0x9005, 0x028f, 0x1590, 0x0294, PQI_HWIF_SRCV, "SR932i-p Gen10+"}, + {0x9005, 0x028f, 0x1590, 0x0381, PQI_HWIF_SRCV, "SR932i-p Gen11"}, + {0x9005, 0x028f, 0x1590, 0x0382, PQI_HWIF_SRCV, "SR308i-p Gen11"}, + {0x9005, 0x028f, 0x1590, 0x0383, PQI_HWIF_SRCV, "SR308i-o Gen11"}, + {0x9005, 0x028f, 0x1590, 0x02db, PQI_HWIF_SRCV, "SR416ie-m Gen11"}, + {0x9005, 0x028f, 0x1590, 0x032e, PQI_HWIF_SRCV, "SR416i-o Gen11"}, + {0x9005, 0x028f, 0x9005, 0x1452, PQI_HWIF_SRCV, "SmartRAID 3200p Ultra"}, + {0x9005, 0x028f, 0x1137, 0x02fe, PQI_HWIF_SRCV, "Cisco 24G TriMode M1 RAID LFF 32D UCSC-RAIDMP1LL32"}, + + /* (MSCC HBA/SMARTHBA/CFF SmartRAID - Lenovo 8X12G 16X12G based) */ + {0x9005, 0x028f, 0x1d49, 0x0220, PQI_HWIF_SRCV, "4350-8i SAS/SATA HBA"}, + {0x9005, 0x028f, 0x1d49, 0x0221, PQI_HWIF_SRCV, "4350-16i SAS/SATA HBA"}, + {0x9005, 0x028f, 0x1d49, 0x0520, PQI_HWIF_SRCV, "5350-8i"}, + {0x9005, 0x028f, 0x1d49, 0x0522, PQI_HWIF_SRCV, "5350-8i INTR"}, + {0x9005, 0x028f, 0x1d49, 0x0620, PQI_HWIF_SRCV, "9350-8i 2GB Flash"}, + {0x9005, 0x028f, 0x1d49, 0x0621, PQI_HWIF_SRCV, "9350-8i 2GB Flash INTR"}, + {0x9005, 0x028f, 0x1d49, 0x0622, PQI_HWIF_SRCV, "9350-16i 4GB Flash"}, + {0x9005, 0x028f, 0x1d49, 0x0623, PQI_HWIF_SRCV, "9350-16i 4GB Flash INTR"}, + + {0, 0, 0, 0, 0, 0} +}; + +struct pqi_ident +pqi_family_identifiers[] = { + {0x9005, 0x028f, 0, 0, PQI_HWIF_SRCV, "Smart Array Storage Controller"}, + {0, 0, 0, 0, 0, 0} +}; diff --git a/sys/dev/smartpqi/smartpqi_defines.h b/sys/dev/smartpqi/smartpqi_defines.h index bb0bb2b709aa..0277abd3e318 100644 --- a/sys/dev/smartpqi/smartpqi_defines.h +++ b/sys/dev/smartpqi/smartpqi_defines.h @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -911,9 +911,14 @@ static inline uint64_t CALC_PERCENT_TOTAL(uint64_t val, uint64_t total) #define CCISS_GETDRIVVER _IOWR(SMARTPQI_IOCTL_BASE, 0, driver_info) #define CCISS_GETPCIINFO _IOWR(SMARTPQI_IOCTL_BASE, 1, pqi_pci_info_t) #define SMARTPQI_PASS_THRU _IOWR(SMARTPQI_IOCTL_BASE, 2, IOCTL_Command_struct) +#define SMARTPQI_BIG_PASS_THRU _IOWR(SMARTPQI_IOCTL_BASE, 3, BIG_IOCTL_Command_struct) #define CCISS_PASSTHRU _IOWR('C', 210, IOCTL_Command_struct) #define CCISS_REGNEWD _IO(CCISS_IOC_MAGIC, 14) +#if !defined(SMARTPQI_BIG_PASSTHRU_SUPPORTED) +#define SMARTPQI_BIG_PASSTHRU_SUPPORTED _IO(SMARTPQI_IOCTL_BASE, 4) +#endif + /*IOCTL pci_info structure */ typedef struct pqi_pci_info { @@ -927,7 +932,7 @@ typedef struct pqi_pci_info typedef struct _driver_info { unsigned char major_version; - unsigned long minor_version; + unsigned char minor_version; unsigned char release_version; unsigned long build_revision; unsigned long max_targets; @@ -938,9 +943,13 @@ typedef struct _driver_info typedef uint8_t *passthru_buf_type_t; #define PQISRC_DRIVER_MAJOR __FreeBSD__ -#define PQISRC_DRIVER_MINOR 4410 +#if __FreeBSD__ <= 14 +#define PQISRC_DRIVER_MINOR 4690 +#else +#define PQISRC_DRIVER_MINOR 2 +#endif #define PQISRC_DRIVER_RELEASE 0 -#define PQISRC_DRIVER_REVISION 2005 +#define PQISRC_DRIVER_REVISION 2008 #define STR(s) # s #define PQISRC_VERSION(a, b, c, d) STR(a.b.c-d) @@ -1234,19 +1243,21 @@ typedef struct sema OS_SEMA_LOCK_T; /* Debug facility */ -#define PQISRC_FLAGS_MASK 0x0000ffff -#define PQISRC_FLAGS_INIT 0x00000001 -#define PQISRC_FLAGS_INFO 0x00000002 -#define PQISRC_FLAGS_FUNC 0x00000004 -#define PQISRC_FLAGS_TRACEIO 0x00000008 -#define PQISRC_FLAGS_DISC 0x00000010 -#define PQISRC_FLAGS_WARN 0x00000020 -#define PQISRC_FLAGS_ERROR 0x00000040 -#define PQISRC_FLAGS_NOTE 0x00000080 +#define PQISRC_FLAGS_MASK 0x0000000000ff +#define PQISRC_FLAGS_INIT 0x0001 +#define PQISRC_FLAGS_INFO 0x0002 +#define PQISRC_FLAGS_FUNC 0x0004 +#define PQISRC_FLAGS_TRACEIO 0x0008 +#define PQISRC_FLAGS_DISC 0x0010 +#define PQISRC_FLAGS_WARN 0x0020 +#define PQISRC_FLAGS_ERROR 0x0040 +#define PQISRC_FLAGS_NOTE 0x0080 + +#define PQISRC_LOG_LEVEL (PQISRC_FLAGS_WARN | PQISRC_FLAGS_ERROR) -#define PQISRC_LOG_LEVEL (PQISRC_FLAGS_WARN | PQISRC_FLAGS_ERROR | PQISRC_FLAGS_NOTE) +extern unsigned long logging_level; -static int logging_level = PQISRC_LOG_LEVEL; +#define DBG_SET_LOGGING_LEVEL(value) logging_level = value & PQISRC_FLAGS_MASK #define DBG_INIT(fmt,args...) \ do { \ @@ -1276,13 +1287,6 @@ static int logging_level = PQISRC_LOG_LEVEL; } \ }while(0); -#define DBG_TRACEIO(fmt,args...) \ - do { \ - if (logging_level & PQISRC_FLAGS_TRACEIO) { \ - printf("[TRACEIO]:[ %s ] [ %d ]"fmt,__func__,__LINE__,##args); \ - } \ - }while(0); - #define DBG_WARN(fmt,args...) \ do { \ if (logging_level & PQISRC_FLAGS_WARN) { \ diff --git a/sys/dev/smartpqi/smartpqi_discovery.c b/sys/dev/smartpqi/smartpqi_discovery.c index ac37c2233762..a7de5a149810 100644 --- a/sys/dev/smartpqi/smartpqi_discovery.c +++ b/sys/dev/smartpqi/smartpqi_discovery.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -189,7 +189,7 @@ pqisrc_set_btl(pqi_scsi_dev_t *device, int bus, int target, int lun) * devices and multi-lun devices */ boolean_t pqisrc_add_softs_entry(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device, - uint8_t *scsi3addr) + uint8_t const *scsi3addr) { /* Add physical devices with targets that need * targets */ @@ -269,7 +269,7 @@ pqisrc_add_softs_entry(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device, } } DBG_ERR("The device is not a physical, lun or ptraid device" - "B %d: T %d: L %d\n", device->bus, device->target, + "B%d:T%d:L%d\n", device->bus, device->target, device->lun ); return false; @@ -283,7 +283,7 @@ add_device_to_dev_list: softs->dev_list[j] = device; break; } - DBG_NOTE("Added device [%d of %d]: B %d: T %d: L %d\n", + DBG_NOTE("Added device [%d of %d]: B%d:T%d:L%d\n", j, softs->num_devs, device->bus, device->target, device->lun); return true; @@ -307,7 +307,6 @@ pqisrc_find_btl_list_index(pqisrc_softstate_t *softs, if(bus == softs->bus_id && target == temp_device->target && lun == temp_device->lun){ - DBG_DISC("Returning device list index %d\n", index); return index; } @@ -322,7 +321,7 @@ pqisrc_find_btl_list_index(pqisrc_softstate_t *softs, /* Return a given index for a specific device within the * softs dev_list */ int -pqisrc_find_device_list_index(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) +pqisrc_find_device_list_index(pqisrc_softstate_t *softs, pqi_scsi_dev_t const *device) { int index; @@ -346,7 +345,7 @@ pqisrc_find_device_list_index(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) /* Delete a given device from the softs dev_list*/ int -pqisrc_delete_softs_entry(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) +pqisrc_delete_softs_entry(pqisrc_softstate_t *softs, pqi_scsi_dev_t const *device) { int index; @@ -354,8 +353,8 @@ pqisrc_delete_softs_entry(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) if (0 <= index && index < MAX_TARGET_BIT) { softs->dev_list[index] = NULL; softs->num_devs--; - DBG_NOTE("Removing device : B %d: T %d: L %d positioned at %d\n", - device->bus, device->target, device->lun, softs->num_devs); + DBG_NOTE("Removing device: B%d:T%d:L%d positioned at %d\n", + device->bus, device->target, device->lun, index); return PQI_STATUS_SUCCESS; } if (index == INVALID_ELEM) { @@ -414,7 +413,7 @@ pqisrc_build_send_raid_request(pqisrc_softstate_t *softs, struct dma_mem device_ int ret = PQI_STATUS_SUCCESS; ib_queue_t *ib_q = &softs->op_raid_ib_q[PQI_DEFAULT_IB_QUEUE]; - ob_queue_t *ob_q = &softs->op_ob_q[PQI_DEFAULT_IB_QUEUE]; + ob_queue_t const *ob_q = &softs->op_ob_q[PQI_DEFAULT_IB_QUEUE]; rcb_t *rcb = NULL; @@ -740,13 +739,13 @@ pqisrc_get_phys_log_device_list(pqisrc_softstate_t *softs, ret = pqisrc_get_physical_logical_luns(softs, SA_REPORT_PHYS, physical_dev_list, phys_data_length); if (ret) { - DBG_ERR("report physical LUNs failed"); + DBG_ERR("report physical LUNs failed\n"); return ret; } ret = pqisrc_get_physical_logical_luns(softs, SA_REPORT_LOG, logical_dev_list, log_data_length); if (ret) { - DBG_ERR("report logical LUNs failed"); + DBG_ERR("report logical LUNs failed\n"); return ret; } @@ -763,7 +762,7 @@ pqisrc_get_phys_log_device_list(pqisrc_softstate_t *softs, ret = pqisrc_get_queue_lun_list(softs, PQI_LOG_EXT_QUEUE_ENABLE, queue_dev_list, queue_data_length); if (ret) { - DBG_ERR("report logical LUNs failed"); + DBG_ERR("report logical LUNs failed\n"); return ret; } @@ -808,13 +807,13 @@ pqisrc_get_phys_log_device_list(pqisrc_softstate_t *softs, } inline boolean_t -pqisrc_is_external_raid_device(pqi_scsi_dev_t *device) +pqisrc_is_external_raid_device(pqi_scsi_dev_t const *device) { return device->is_external_raid_device; } static inline boolean_t -pqisrc_is_external_raid_addr(uint8_t *scsi3addr) +pqisrc_is_external_raid_addr(uint8_t const *scsi3addr) { return scsi3addr[2] != 0; } @@ -940,12 +939,12 @@ out: /* Validate the RAID map parameters */ static int pqisrc_raid_map_validation(pqisrc_softstate_t *softs, - pqi_scsi_dev_t *device, pqisrc_raid_map_t *raid_map) + pqi_scsi_dev_t const *device, pqisrc_raid_map_t *raid_map) { char *error_msg; uint32_t raidmap_size; uint32_t r5or6_blocks_per_row; -/* unsigned phys_dev_num; */ + /* unsigned phys_dev_num; */ DBG_FUNC("IN\n"); @@ -1033,7 +1032,7 @@ pqisrc_get_device_raidmap(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) if (raidmap_reported_size <= raidmap_alloc_size) break; - DBG_NOTE("Raid map is larger than 1024 entries, request once again"); + DBG_NOTE("Raid map is larger than 1024 entries, request once again\n"); os_mem_free(softs, (char*)raid_map, raidmap_alloc_size); raidmap_alloc_size = raidmap_reported_size; @@ -1331,7 +1330,7 @@ pqisrc_get_physical_device_info(pqisrc_softstate_t *softs, /* Function used to find the entry of the device in a list */ static device_status_t pqisrc_scsi_find_entry(pqisrc_softstate_t *softs, - pqi_scsi_dev_t *device_to_find, pqi_scsi_dev_t **same_device) + pqi_scsi_dev_t const *device_to_find, pqi_scsi_dev_t **same_device) { pqi_scsi_dev_t *device; int i; @@ -1361,7 +1360,7 @@ pqisrc_scsi_find_entry(pqisrc_softstate_t *softs, /* Update the newly added devices as existed device */ static void -pqisrc_exist_device_update(pqisrc_softstate_t *softs, +pqisrc_exist_device_update(pqisrc_softstate_t const *softs, pqi_scsi_dev_t *device_exist, pqi_scsi_dev_t *new_device) { DBG_FUNC("IN\n"); @@ -1395,15 +1394,13 @@ pqisrc_exist_device_update(pqisrc_softstate_t *softs, device_exist->offload_config = new_device->offload_config; device_exist->offload_enabled_pending = new_device->offload_enabled_pending; - if (device_exist->offload_to_mirror) - os_mem_free(softs, - (int *) device_exist->offload_to_mirror, - sizeof(*(device_exist->offload_to_mirror))); + if (device_exist->offload_to_mirror) { + device_exist->temp_offload_to_mirror = device_exist->offload_to_mirror; + } device_exist->offload_to_mirror = new_device->offload_to_mirror; - if (device_exist->raid_map) - os_mem_free(softs, - (char *)device_exist->raid_map, - sizeof(*device_exist->raid_map)); + if (device_exist->raid_map) { + device_exist->temp_raid_map = device_exist->raid_map; + } device_exist->raid_map = new_device->raid_map; /* To prevent these from being freed later. */ new_device->raid_map = NULL; @@ -1416,7 +1413,7 @@ static int pqisrc_add_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) { DBG_FUNC("IN\n"); - DBG_NOTE("vendor: %s model: %s bus:%d target:%d lun:%d is_physical_device:0x%x expose_device:0x%x volume_offline 0x%x volume_status 0x%x \n", + DBG_NOTE("vendor: %s model: %s B%d:T%d:L%d is_physical_device:0x%x expose_device:0x%x volume_offline 0x%x volume_status 0x%x \n", device->vendor, device->model, device->bus, device->target, device->lun, device->is_physical_device, device->expose_device, device->volume_offline, device->volume_status); device->invalid = false; @@ -1439,7 +1436,7 @@ void pqisrc_remove_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) { DBG_FUNC("IN\n"); - DBG_NOTE("vendor: %s model: %s bus:%d target:%d lun:%d is_physical_device:0x%x expose_device:0x%x volume_offline 0x%x volume_status 0x%x \n", + DBG_NOTE("vendor: %s model: %s B%d:T%d:L%d is_physical_device:0x%x expose_device:0x%x volume_offline 0x%x volume_status 0x%x \n", device->vendor, device->model, device->bus, device->target, device->lun, device->is_physical_device, device->expose_device, device->volume_offline, device->volume_status); device->invalid = true; if (device->expose_device == false) { @@ -1460,63 +1457,9 @@ pqisrc_remove_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) } -/* - * When exposing new device to OS fails then adjst list according to the - * mid scsi list - */ -static void -pqisrc_adjust_list(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) -{ - int i; - unsigned char addr1[8], addr2[8]; - pqi_scsi_dev_t *temp_device; - DBG_FUNC("IN\n"); - - if (!device) { - DBG_ERR("softs = %p: device is NULL !!!\n", softs); - return; - } - - OS_ACQUIRE_SPINLOCK(&softs->devlist_lock); - uint8_t *scsi3addr; - /*For external raid device, there can be multiple luns - *with same target. So while freeing external raid device, - *free target only after removing all luns with same target.*/ - if (pqisrc_is_external_raid_device(device)) { - memcpy(addr1, device->scsi3addr, 8); - for(i = 0; i < PQI_MAX_DEVICES; i++) { - if(softs->dev_list[i] == NULL) - continue; - temp_device = softs->dev_list[i]; - memcpy(addr2, temp_device->scsi3addr, 8); - if(memcmp(addr1, addr2, 8) == 0) { - continue; - } - if (addr1[2] == addr2[2]) { - break; - } - } - if(i == PQI_MAX_DEVICES) { - pqisrc_remove_target_bit(softs, device->target); - } - } - - if(pqisrc_delete_softs_entry(softs, device) == PQI_STATUS_SUCCESS){ - scsi3addr = device->scsi3addr; - if (!pqisrc_is_logical_device(device) && !MASKED_DEVICE(scsi3addr)){ - DBG_NOTE("About to remove target bit %d \n", device->target); - pqisrc_remove_target_bit(softs, device->target); - } - } - OS_RELEASE_SPINLOCK(&softs->devlist_lock); - pqisrc_device_mem_free(softs, device); - - DBG_FUNC("OUT\n"); -} - /* Debug routine used to display the RAID volume status of the device */ static void -pqisrc_display_volume_status(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) +pqisrc_display_volume_status(pqisrc_softstate_t *softs, pqi_scsi_dev_t const *device) { char *status; @@ -1590,7 +1533,7 @@ pqisrc_display_volume_status(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) break; } - DBG_NOTE("scsi BTL %d:%d:%d %s\n", + DBG_NOTE("scsi B%d:T%d:L%d %s\n", device->bus, device->target, device->lun, status); DBG_FUNC("OUT\n"); } @@ -1635,7 +1578,7 @@ pqisrc_free_device(pqisrc_softstate_t * softs, pqi_scsi_dev_t *device) /* Find the entry in device list for the freed device softs->dev_list[i]& *make it NULL before freeing the device memory */ - index = pqisrc_find_device_list_index(softs, device); + index = pqisrc_find_btl_list_index(softs, device->bus, device->target, device->lun); OS_ACQUIRE_SPINLOCK(&softs->devlist_lock); scsi3addr = device->scsi3addr; @@ -1669,13 +1612,14 @@ pqisrc_free_device(pqisrc_softstate_t * softs, pqi_scsi_dev_t *device) softs->dev_list[index] = NULL; if (device->expose_device == true){ pqisrc_delete_softs_entry(softs, device); - DBG_NOTE("Removed memory for device : B %d: T %d: L %d\n", + DBG_NOTE("Removed memory for device: B%d:T%d:L%d\n", device->bus, device->target, device->lun); OS_RELEASE_SPINLOCK(&softs->devlist_lock); pqisrc_device_mem_free(softs, device); } else { OS_RELEASE_SPINLOCK(&softs->devlist_lock); } + } @@ -1684,7 +1628,6 @@ static void pqisrc_update_device_list(pqisrc_softstate_t *softs, pqi_scsi_dev_t *new_device_list[], int num_new_devices) { - int ret; int i; device_status_t dev_status; pqi_scsi_dev_t *device; @@ -1755,8 +1698,7 @@ pqisrc_update_device_list(pqisrc_softstate_t *softs, if(device == NULL) continue; if (device->device_gone) { - if(device->in_remove == true) - { + if(device->in_remove == true) { continue; } device->in_remove = true; @@ -1794,7 +1736,7 @@ pqisrc_update_device_list(pqisrc_softstate_t *softs, continue; if (device->offload_enabled != device->offload_enabled_pending) { - DBG_NOTE("[%d:%d:%d]Changing AIO to %d (was %d)\n", + DBG_NOTE("[B%d:T%d:L%d]Changing AIO to %d (was %d)\n", device->bus, device->target, device->lun, device->offload_enabled_pending, device->offload_enabled); @@ -1831,24 +1773,14 @@ pqisrc_update_device_list(pqisrc_softstate_t *softs, device->firmware_queue_depth_set == false) device->queue_depth = PQI_LOGICAL_DISK_DEFAULT_MAX_QUEUE_DEPTH; - if (device->scsi_rescan) { - os_rescan_target(softs, device); - } } - softs->ld_rescan = false; OS_RELEASE_SPINLOCK(&softs->devlist_lock); for(i = 0; i < nadded; i++) { device = added[i]; if (device->expose_device) { - ret = pqisrc_add_device(softs, device); - if (ret) { - DBG_WARN("scsi %d:%d:%d addition failed, device not added\n", - device->bus, device->target, device->lun); - pqisrc_adjust_list(softs, device); - continue; - } + pqisrc_add_device(softs, device); } pqisrc_display_device_info(softs, "added", device); @@ -1874,7 +1806,22 @@ pqisrc_update_device_list(pqisrc_softstate_t *softs, DBG_DISC("Current device %d : B%d:T%d:L%d\n", i, device->bus, device->target, device->lun); + if (device->scsi_rescan) { + os_rescan_target(softs, device); + } + if (device->temp_offload_to_mirror) { + os_mem_free(softs, + (int *) device->temp_offload_to_mirror, + sizeof(*(device->temp_offload_to_mirror))); + } + if (device->temp_raid_map) { + os_mem_free(softs, + (int *) device->temp_raid_map, + sizeof(*(device->temp_raid_map))); + } + } + softs->ld_rescan = false; free_and_out: if (added) @@ -1928,6 +1875,8 @@ pqisrc_write_driver_version_to_host_wellness(pqisrc_softstate_t *softs) } host_wellness_driver_ver->driver_version[sizeof(host_wellness_driver_ver->driver_version) - 1] = '\0'; + host_wellness_driver_ver->dont_write_tag[0] = 'D'; + host_wellness_driver_ver->dont_write_tag[1] = 'W'; host_wellness_driver_ver->end_tag[0] = 'Z'; host_wellness_driver_ver->end_tag[1] = 'Z'; @@ -1941,7 +1890,7 @@ pqisrc_write_driver_version_to_host_wellness(pqisrc_softstate_t *softs) os_mem_free(softs, (char *)host_wellness_driver_ver, data_length); - DBG_FUNC("OUT"); + DBG_FUNC("OUT\n"); return rval; } @@ -1974,8 +1923,8 @@ pqisrc_write_current_time_to_host_wellness(pqisrc_softstate_t *softs) host_wellness_time->start_tag[3] = '>'; host_wellness_time->time_tag[0] = 'T'; host_wellness_time->time_tag[1] = 'D'; - host_wellness_time->time_length = LE_16(offsetof(struct bmic_host_wellness_time, time_length) - - offsetof(struct bmic_host_wellness_time, century)); + host_wellness_time->time_length = LE_16(offsetof(struct bmic_host_wellness_time, dont_write_tag) - + offsetof(struct bmic_host_wellness_time, hour)); os_get_time(host_wellness_time); @@ -1994,12 +1943,12 @@ pqisrc_write_current_time_to_host_wellness(pqisrc_softstate_t *softs) os_mem_free(softs, (char *)host_wellness_time, data_length); - DBG_FUNC("OUT"); + DBG_FUNC("OUT\n"); return rval; } static void pqisrc_get_device_vpd_info(pqisrc_softstate_t *softs, - bmic_ident_physdev_t *bmic_phy_info,pqi_scsi_dev_t *device) + bmic_ident_physdev_t const *bmic_phy_info,pqi_scsi_dev_t *device) { DBG_FUNC("IN\n"); memcpy(&device->wwid, &bmic_phy_info->padding[79], sizeof(device->wwid)); @@ -2102,7 +2051,7 @@ pqisrc_scan_devices(pqisrc_softstate_t *softs) scsi3addr = lun_ext_entry->lunid; - /* Save the target sas adderess for external raid device */ + /* Save the target sas address for external raid device */ if(lun_ext_entry->device_type == CONTROLLER_DEVICE) { #ifdef PQI_NEED_RESCAN_TIMER_FOR_RBOD_HOTPLUG num_ext_raid_devices++; diff --git a/sys/dev/smartpqi/smartpqi_event.c b/sys/dev/smartpqi/smartpqi_event.c index 88dcf45dd08a..77a70f9fb031 100644 --- a/sys/dev/smartpqi/smartpqi_event.c +++ b/sys/dev/smartpqi/smartpqi_event.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -59,7 +59,7 @@ pqisrc_wait_for_rescan_complete(pqisrc_softstate_t *softs) */ static void pqisrc_acknowledge_event(pqisrc_softstate_t *softs, - struct pqi_event *event) + struct pqi_event const *event) { int ret; @@ -225,7 +225,7 @@ pqisrc_process_event_intr_src(pqisrc_softstate_t *softs,int obq_id) os_eventtaskqueue_enqueue(softs); } - DBG_FUNC("OUT"); + DBG_FUNC("OUT\n"); return PQI_STATUS_SUCCESS; @@ -241,7 +241,7 @@ pqisrc_build_send_vendor_request(pqisrc_softstate_t *softs, { int ret = PQI_STATUS_SUCCESS; ib_queue_t *op_ib_q = &softs->op_raid_ib_q[PQI_DEFAULT_IB_QUEUE]; - ob_queue_t *ob_q = &softs->op_ob_q[PQI_DEFAULT_IB_QUEUE]; + ob_queue_t const *ob_q = &softs->op_ob_q[PQI_DEFAULT_IB_QUEUE]; rcb_t *rcb = NULL; @@ -341,7 +341,7 @@ err_out: static int pqi_event_configure(pqisrc_softstate_t *softs , pqi_event_config_request_t *request, - dma_mem_t *buff) + dma_mem_t const *buff) { int ret = PQI_STATUS_SUCCESS; @@ -417,7 +417,7 @@ pqisrc_report_event_config(pqisrc_softstate_t *softs) softs->event_config.num_event_descriptors = MIN(event_config_p->num_event_descriptors, PQI_MAX_EVENT_DESCRIPTORS) ; - for (i = 0; i < softs->event_config.num_event_descriptors; i++) { + for (i=0; i < softs->event_config.num_event_descriptors; i++) { softs->event_config.descriptors[i].event_type = event_config_p->descriptors[i].event_type; } @@ -477,7 +477,7 @@ pqisrc_set_event_config(pqisrc_softstate_t *softs) event_config_p->num_event_descriptors = softs->event_config.num_event_descriptors; - for (i = 0; i < softs->event_config.num_event_descriptors; i++) { + for (i=0; i < softs->event_config.num_event_descriptors; i++) { event_config_p->descriptors[i].event_type = softs->event_config.descriptors[i].event_type; if( pqisrc_event_type_to_event_index(event_config_p->descriptors[i].event_type) != -1) diff --git a/sys/dev/smartpqi/smartpqi_features.c b/sys/dev/smartpqi/smartpqi_features.c index 2a53dbe654b1..ae6114ef066b 100644 --- a/sys/dev/smartpqi/smartpqi_features.c +++ b/sys/dev/smartpqi/smartpqi_features.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/dev/smartpqi/smartpqi_helper.c b/sys/dev/smartpqi/smartpqi_helper.c index 741ac0a05a06..9454fa8b63ab 100644 --- a/sys/dev/smartpqi/smartpqi_helper.c +++ b/sys/dev/smartpqi/smartpqi_helper.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,7 +30,7 @@ * Function used to validate the adapter health. */ boolean_t -pqisrc_ctrl_offline(pqisrc_softstate_t *softs) +pqisrc_ctrl_offline(pqisrc_softstate_t const *softs) { DBG_FUNC("IN\n"); @@ -83,12 +83,10 @@ pqisrc_take_ctrl_offline(pqisrc_softstate_t *softs) { DBG_FUNC("IN\n"); - int lockupcode = 0; - softs->ctrl_online = false; if (SIS_IS_KERNEL_PANIC(softs)) { - lockupcode = PCI_MEM_GET32(softs, &softs->ioa_reg->mb[7], LEGACY_SIS_SRCV_OFFSET_MAILBOX_7); + int lockupcode = PCI_MEM_GET32(softs, &softs->ioa_reg->mb[7], LEGACY_SIS_SRCV_OFFSET_MAILBOX_7); DBG_ERR("Controller FW is not running, Lockup code = %x\n", lockupcode); } else { @@ -172,7 +170,7 @@ pqisrc_wait_on_condition(pqisrc_softstate_t *softs, rcb_t *rcb, } if (pqisrc_ctrl_offline(softs)) { - DBG_ERR("Controller is Offline"); + DBG_ERR("Controller is Offline\n"); ret = PQI_STATUS_FAILURE; break; } @@ -187,29 +185,29 @@ pqisrc_wait_on_condition(pqisrc_softstate_t *softs, rcb_t *rcb, /* Function used to validate the device wwid. */ boolean_t -pqisrc_device_equal(pqi_scsi_dev_t *dev1, - pqi_scsi_dev_t *dev2) +pqisrc_device_equal(pqi_scsi_dev_t const *dev1, + pqi_scsi_dev_t const *dev2) { return dev1->wwid == dev2->wwid; } /* Function used to validate the device scsi3addr. */ boolean_t -pqisrc_scsi3addr_equal(uint8_t *scsi3addr1, uint8_t *scsi3addr2) +pqisrc_scsi3addr_equal(uint8_t const *scsi3addr1, uint8_t const *scsi3addr2) { return memcmp(scsi3addr1, scsi3addr2, 8) == 0; } /* Function used to validate hba_lunid */ boolean_t -pqisrc_is_hba_lunid(uint8_t *scsi3addr) +pqisrc_is_hba_lunid(uint8_t const *scsi3addr) { return pqisrc_scsi3addr_equal(scsi3addr, RAID_CTLR_LUNID); } /* Function used to validate type of device */ boolean_t -pqisrc_is_logical_device(pqi_scsi_dev_t *device) +pqisrc_is_logical_device(pqi_scsi_dev_t const *device) { return !device->is_physical_device; } @@ -256,10 +254,10 @@ pqisrc_raidlevel_to_string(uint8_t raid_level) /* Debug routine for displaying device info */ void pqisrc_display_device_info(pqisrc_softstate_t *softs, - char *action, pqi_scsi_dev_t *device) + char const *action, pqi_scsi_dev_t *device) { if (device->is_physical_device) { - DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " + DBG_NOTE("%s scsi B%d:T%d:L%d %.8s %.16s %-12s " "SSDSmartPathCap%c En%c Exp%c qd=%d\n", action, device->bus, @@ -273,7 +271,7 @@ void pqisrc_display_device_info(pqisrc_softstate_t *softs, device->expose_device ? '+' : '-', device->queue_depth); } else if (device->devtype == RAID_DEVICE) { - DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " + DBG_NOTE("%s scsi B%d:T%d:L%d %.8s %.16s %-12s " "SSDSmartPathCap%c En%c Exp%c qd=%d\n", action, device->bus, @@ -287,7 +285,7 @@ void pqisrc_display_device_info(pqisrc_softstate_t *softs, device->expose_device ? '+' : '-', device->queue_depth); } else if (device->devtype == CONTROLLER_DEVICE) { - DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " + DBG_NOTE("%s scsi B%d:T%d:L%d %.8s %.16s %-12s " "SSDSmartPathCap%c En%c Exp%c qd=%d\n", action, device->bus, @@ -301,7 +299,7 @@ void pqisrc_display_device_info(pqisrc_softstate_t *softs, device->expose_device ? '+' : '-', device->queue_depth); } else { - DBG_NOTE("%s scsi BTL %d:%d:%d: %.8s %.16s %-12s " + DBG_NOTE("%s scsi B%d:T%d:L%d %.8s %.16s %-12s " "SSDSmartPathCap%c En%c Exp%c qd=%d devtype=%d\n", action, device->bus, @@ -335,7 +333,9 @@ check_struct_sizes(void) 64 bit and 32 bit system*/ ASSERT(sizeof(IOCTL_Command_struct)== 86 || sizeof(IOCTL_Command_struct)== 82); - ASSERT(sizeof(struct bmic_host_wellness_driver_version)== 42); + ASSERT(sizeof(BIG_IOCTL_Command_struct)== 88 || + sizeof(BIG_IOCTL_Command_struct)== 84); + ASSERT(sizeof(struct bmic_host_wellness_driver_version)== 44); ASSERT(sizeof(struct bmic_host_wellness_time)== 20); ASSERT(sizeof(struct pqi_dev_adminq_cap)== 8); ASSERT(sizeof(struct admin_q_param)== 4); @@ -388,7 +388,7 @@ void check_device_pending_commands_to_complete(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) { uint32_t tag = softs->max_outstanding_io, active_requests; - uint64_t timeout = 0, delay_in_usec = 1000; /* In micro Seconds */ + uint64_t timeout = 0, delay_in_usec = 1000; /* In microseconds */ rcb_t* rcb; DBG_FUNC("IN\n"); diff --git a/sys/dev/smartpqi/smartpqi_helper.h b/sys/dev/smartpqi/smartpqi_helper.h index 507caeb9b0b6..362eb0d05379 100644 --- a/sys/dev/smartpqi/smartpqi_helper.h +++ b/sys/dev/smartpqi/smartpqi_helper.h @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/dev/smartpqi/smartpqi_includes.h b/sys/dev/smartpqi/smartpqi_includes.h index a8682e8a848d..30846b1a1d6c 100644 --- a/sys/dev/smartpqi/smartpqi_includes.h +++ b/sys/dev/smartpqi/smartpqi_includes.h @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/dev/smartpqi/smartpqi_init.c b/sys/dev/smartpqi/smartpqi_init.c index 41c990a15909..fde17a542421 100644 --- a/sys/dev/smartpqi/smartpqi_init.c +++ b/sys/dev/smartpqi/smartpqi_init.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -234,7 +234,7 @@ pqisrc_decide_opq_config(pqisrc_softstate_t *softs) DBG_FUNC("IN\n"); - DBG_INIT("softs->intr_count : %d softs->num_cpus_online : %d", + DBG_INIT("softs->intr_count : %d softs->num_cpus_online : %d\n", softs->intr_count, softs->num_cpus_online); /* TODO : Get the number of IB and OB queues from OS layer */ @@ -437,7 +437,6 @@ int pqi_reset(pqisrc_softstate_t *softs) { int ret = PQI_STATUS_SUCCESS; - uint32_t val = 0; pqi_reset_reg_t pqi_reset_reg; DBG_FUNC("IN\n"); @@ -445,7 +444,7 @@ pqi_reset(pqisrc_softstate_t *softs) if (true == softs->ctrl_in_pqi_mode) { if (softs->pqi_reset_quiesce_allowed) { - val = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db, + int val = PCI_MEM_GET32(softs, &softs->ioa_reg->host_to_ioa_db, LEGACY_SIS_IDBR); val |= SIS_PQI_RESET_QUIESCE; PCI_MEM_PUT32(softs, &softs->ioa_reg->host_to_ioa_db, @@ -629,7 +628,7 @@ pqisrc_wait_for_cmnd_complete(pqisrc_softstate_t *softs) int count = 0; int ret = PQI_STATUS_SUCCESS; - DBG_NOTE("softs->taglist.num_elem : %u",softs->taglist.num_elem); + DBG_NOTE("softs->taglist.num_elem : %u\n",softs->taglist.num_elem); if (softs->taglist.num_elem == softs->max_outstanding_io) return ret; @@ -650,7 +649,7 @@ pqisrc_wait_for_cmnd_complete(pqisrc_softstate_t *softs) OS_SLEEP(1000); count++; if(count % 1000 == 0) { - DBG_WARN("Waited for %d seconds", count/1000); + DBG_WARN("Waited for %d seconds\n", count/1000); } if (count >= PQI_QUIESCE_TIMEOUT) { return PQI_STATUS_FAILURE; @@ -849,7 +848,7 @@ pqisrc_init(pqisrc_softstate_t *softs) /* update driver version in to FW */ ret = pqisrc_write_driver_version_to_host_wellness(softs); if (ret) { - DBG_ERR(" Failed to update driver version in to FW"); + DBG_ERR(" Failed to update driver version in to FW\n"); goto err_host_wellness; } diff --git a/sys/dev/smartpqi/smartpqi_intr.c b/sys/dev/smartpqi/smartpqi_intr.c index a62bdc9e8389..1971ac03a556 100644 --- a/sys/dev/smartpqi/smartpqi_intr.c +++ b/sys/dev/smartpqi/smartpqi_intr.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,7 +35,6 @@ os_get_processor_config(pqisrc_softstate_t *softs) { DBG_FUNC("IN\n"); softs->num_cpus_online = mp_ncpus; - bsd_set_hint_adapter_cpu_config(softs); DBG_FUNC("OUT\n"); return PQI_STATUS_SUCCESS; diff --git a/sys/dev/smartpqi/smartpqi_ioctl.c b/sys/dev/smartpqi/smartpqi_ioctl.c index 2bdc5c09e916..7fd68b1a3263 100644 --- a/sys/dev/smartpqi/smartpqi_ioctl.c +++ b/sys/dev/smartpqi/smartpqi_ioctl.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -74,7 +74,7 @@ smartpqi_close(struct cdev *cdev, int flags, int devtype, * ioctl for getting driver info */ static void -smartpqi_get_driver_info_ioctl(caddr_t udata, struct cdev *cdev) +smartpqi_get_driver_info_ioctl(caddr_t udata, struct cdev const *cdev) { struct pqisrc_softstate *softs = cdev->si_drv1; pdriver_info driver_info = (pdriver_info)udata; @@ -82,7 +82,11 @@ smartpqi_get_driver_info_ioctl(caddr_t udata, struct cdev *cdev) DBG_FUNC("IN udata = %p cdev = %p\n", udata, cdev); driver_info->major_version = PQISRC_DRIVER_MAJOR; +#if __FreeBSD__ <= 14 + driver_info->minor_version = (unsigned char) ((PQISRC_DRIVER_MINOR >> 4) & 0xFF); +#else driver_info->minor_version = PQISRC_DRIVER_MINOR; +#endif driver_info->release_version = PQISRC_DRIVER_RELEASE; driver_info->build_revision = PQISRC_DRIVER_REVISION; driver_info->max_targets = PQI_MAX_DEVICES - 1; @@ -96,7 +100,7 @@ smartpqi_get_driver_info_ioctl(caddr_t udata, struct cdev *cdev) * ioctl for getting controller info */ static void -smartpqi_get_pci_info_ioctl(caddr_t udata, struct cdev *cdev) +smartpqi_get_pci_info_ioctl(caddr_t udata, struct cdev const *cdev) { struct pqisrc_softstate *softs = cdev->si_drv1; device_t dev = softs->os_specific.pqi_dev; @@ -165,6 +169,13 @@ smartpqi_ioctl(struct cdev *cdev, u_long cmd, caddr_t udata, pqi_status = pqisrc_passthru_ioctl(softs, udata, 0); bsd_status = pqi_status_to_bsd_ioctl_status(pqi_status); break; + case SMARTPQI_BIG_PASS_THRU: + pqi_status = pqisrc_big_passthru_ioctl(softs, udata, 0); + bsd_status = pqi_status_to_bsd_ioctl_status(pqi_status); + break; + case SMARTPQI_BIG_PASSTHRU_SUPPORTED: + bsd_status = BSD_SUCCESS; + break; case CCISS_REGNEWD: pqi_status = pqisrc_scan_devices(softs); bsd_status = pqi_status_to_bsd_ioctl_status(pqi_status); @@ -242,7 +253,7 @@ pqisrc_passthru_ioctl(struct pqisrc_softstate *softs, void *arg, int mode) pqisrc_raid_req_t request; raid_path_error_info_elem_t error_info; ib_queue_t *ib_q = &softs->op_raid_ib_q[PQI_DEFAULT_IB_QUEUE]; - ob_queue_t *ob_q = &softs->op_ob_q[PQI_DEFAULT_IB_QUEUE]; + ob_queue_t const *ob_q = &softs->op_ob_q[PQI_DEFAULT_IB_QUEUE]; rcb_t *rcb = NULL; memset(&request, 0, sizeof(request)); @@ -418,3 +429,195 @@ out: DBG_FUNC("Failed OUT\n"); return PQI_STATUS_FAILURE; } + +/* + * Function used to send big passthru commands to adapter + * to support management tools. For eg. ssacli, sscon. + */ +int +pqisrc_big_passthru_ioctl(struct pqisrc_softstate *softs, void *arg, int mode) +{ + int ret; + char *drv_buf = NULL; + uint32_t tag = 0; + BIG_IOCTL_Command_struct *iocommand = (BIG_IOCTL_Command_struct *)arg; + dma_mem_t ioctl_dma_buf; + pqisrc_raid_req_t request; + raid_path_error_info_elem_t error_info; + ib_queue_t *ib_q = &softs->op_raid_ib_q[PQI_DEFAULT_IB_QUEUE]; + ob_queue_t const *ob_q = &softs->op_ob_q[PQI_DEFAULT_IB_QUEUE]; + rcb_t *rcb = NULL; + + memset(&request, 0, sizeof(request)); + memset(&error_info, 0, sizeof(error_info)); + + DBG_FUNC("IN\n"); + + if (pqisrc_ctrl_offline(softs)) + return PQI_STATUS_FAILURE; + + if (!arg) + return PQI_STATUS_FAILURE; + + if (iocommand->buf_size < 1 && + iocommand->Request.Type.Direction != PQIIOCTL_NONE) + return PQI_STATUS_FAILURE; + if (iocommand->Request.CDBLen > sizeof(request.cmd.cdb)) + return PQI_STATUS_FAILURE; + + switch (iocommand->Request.Type.Direction) { + case PQIIOCTL_NONE: + case PQIIOCTL_WRITE: + case PQIIOCTL_READ: + case PQIIOCTL_BIDIRECTIONAL: + break; + default: + return PQI_STATUS_FAILURE; + } + + if (iocommand->buf_size > 0) { + memset(&ioctl_dma_buf, 0, sizeof(struct dma_mem)); + os_strlcpy(ioctl_dma_buf.tag, "Ioctl_PassthruCmd_Buffer", sizeof(ioctl_dma_buf.tag)); + ioctl_dma_buf.size = iocommand->buf_size; + ioctl_dma_buf.align = PQISRC_DEFAULT_DMA_ALIGN; + /* allocate memory */ + ret = os_dma_mem_alloc(softs, &ioctl_dma_buf); + if (ret) { + DBG_ERR("Failed to Allocate dma mem for Ioctl PassthruCmd Buffer : %d\n", ret); + goto out; + } + + DBG_IO("ioctl_dma_buf.dma_addr = %p\n",(void*)ioctl_dma_buf.dma_addr); + DBG_IO("ioctl_dma_buf.virt_addr = %p\n",(void*)ioctl_dma_buf.virt_addr); + + drv_buf = (char *)ioctl_dma_buf.virt_addr; + if (iocommand->Request.Type.Direction & PQIIOCTL_WRITE) { + ret = os_copy_from_user(softs, (void *)drv_buf, (void *)iocommand->buf, iocommand->buf_size, mode); + if (ret != 0) { + goto free_mem; + } + } + } + + request.header.iu_type = PQI_IU_TYPE_RAID_PATH_IO_REQUEST; + request.header.iu_length = offsetof(pqisrc_raid_req_t, sg_descriptors[1]) - + PQI_REQUEST_HEADER_LENGTH; + memcpy(request.lun_number, iocommand->LUN_info.LunAddrBytes, + sizeof(request.lun_number)); + memcpy(request.cmd.cdb, iocommand->Request.CDB, iocommand->Request.CDBLen); + request.additional_cdb_bytes_usage = PQI_ADDITIONAL_CDB_BYTES_0; + + switch (iocommand->Request.Type.Direction) { + case PQIIOCTL_NONE: + request.data_direction = SOP_DATA_DIR_NONE; + break; + case PQIIOCTL_WRITE: + request.data_direction = SOP_DATA_DIR_FROM_DEVICE; + break; + case PQIIOCTL_READ: + request.data_direction = SOP_DATA_DIR_TO_DEVICE; + break; + case PQIIOCTL_BIDIRECTIONAL: + request.data_direction = SOP_DATA_DIR_BIDIRECTIONAL; + break; + } + + request.task_attribute = SOP_TASK_ATTRIBUTE_SIMPLE; + if (iocommand->buf_size > 0) { + request.buffer_length = iocommand->buf_size; + request.sg_descriptors[0].addr = ioctl_dma_buf.dma_addr; + request.sg_descriptors[0].len = iocommand->buf_size; + request.sg_descriptors[0].flags = SG_FLAG_LAST; + } + tag = pqisrc_get_tag(&softs->taglist); + if (INVALID_ELEM == tag) { + DBG_ERR("Tag not available\n"); + goto free_mem; + } + request.request_id = tag; + request.response_queue_id = ob_q->q_id; + request.error_index = request.request_id; + if (softs->timeout_in_passthrough) { + request.timeout_in_sec = iocommand->Request.Timeout; + } + + rcb = &softs->rcb[tag]; + rcb->success_cmp_callback = pqisrc_process_internal_raid_response_success; + rcb->error_cmp_callback = pqisrc_process_internal_raid_response_error; + rcb->tag = tag; + rcb->req_pending = true; + /* Submit Command */ + ret = pqisrc_submit_cmnd(softs, ib_q, &request); + if (ret != PQI_STATUS_SUCCESS) { + DBG_ERR("Unable to submit command\n"); + goto err_out; + } + + ret = pqisrc_wait_on_condition(softs, rcb, PQISRC_PASSTHROUGH_CMD_TIMEOUT); + if (ret != PQI_STATUS_SUCCESS) { + DBG_ERR("Passthru IOCTL cmd timed out !!\n"); + goto err_out; + } + + memset(&iocommand->error_info, 0, sizeof(iocommand->error_info)); + + + if (rcb->status) { + size_t sense_data_length; + + memcpy(&error_info, rcb->error_info, sizeof(error_info)); + iocommand->error_info.ScsiStatus = error_info.status; + sense_data_length = error_info.sense_data_len; + + if (!sense_data_length) + sense_data_length = error_info.resp_data_len; + + if (sense_data_length && + (sense_data_length > sizeof(error_info.data))) + sense_data_length = sizeof(error_info.data); + + if (sense_data_length) { + if (sense_data_length > + sizeof(iocommand->error_info.SenseInfo)) + sense_data_length = + sizeof(iocommand->error_info.SenseInfo); + memcpy (iocommand->error_info.SenseInfo, + error_info.data, sense_data_length); + iocommand->error_info.SenseLen = sense_data_length; + } + + if (error_info.data_out_result == PQI_RAID_DATA_IN_OUT_UNDERFLOW) { + rcb->status = PQI_STATUS_SUCCESS; + } + } + + if (rcb->status == PQI_STATUS_SUCCESS && iocommand->buf_size > 0 && + (iocommand->Request.Type.Direction & PQIIOCTL_READ)) { + + ret = os_copy_to_user(softs, (void*)iocommand->buf, (void*)drv_buf, iocommand->buf_size, mode); + if (ret != 0) { + DBG_ERR("Failed to copy the response\n"); + goto err_out; + } + } + + os_reset_rcb(rcb); + pqisrc_put_tag(&softs->taglist, request.request_id); + if (iocommand->buf_size > 0) + os_dma_mem_free(softs,&ioctl_dma_buf); + + DBG_FUNC("OUT\n"); + return PQI_STATUS_SUCCESS; + +err_out: + os_reset_rcb(rcb); + pqisrc_put_tag(&softs->taglist, request.request_id); + +free_mem: + if (iocommand->buf_size > 0) + os_dma_mem_free(softs, &ioctl_dma_buf); + +out: + DBG_FUNC("Failed OUT\n"); + return PQI_STATUS_FAILURE; +}
\ No newline at end of file diff --git a/sys/dev/smartpqi/smartpqi_ioctl.h b/sys/dev/smartpqi/smartpqi_ioctl.h index 633465aeb8cd..ef4678ad5a3b 100644 --- a/sys/dev/smartpqi/smartpqi_ioctl.h +++ b/sys/dev/smartpqi/smartpqi_ioctl.h @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -137,5 +137,12 @@ typedef struct pqi_ioctl_passthruCmd_struct { }OS_ATTRIBUTE_PACKED IOCTL_Command_struct; +typedef struct _BIG_IOCTL_Command_struct { + LUNAddr_struct LUN_info; + RequestBlock_struct Request; + ErrorInfo_struct error_info; + DWORD buf_size; /* size in bytes of the buf */ + passthru_buf_type_t buf; +}OS_ATTRIBUTE_PACKED BIG_IOCTL_Command_struct; #endif /* _PQI_IOCTL_H_ */ diff --git a/sys/dev/smartpqi/smartpqi_main.c b/sys/dev/smartpqi/smartpqi_main.c index 402841bbf4d6..1f006939bf7c 100644 --- a/sys/dev/smartpqi/smartpqi_main.c +++ b/sys/dev/smartpqi/smartpqi_main.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,294 +25,18 @@ /* - * Driver for the Microsemi Smart storage controllers + * Driver for the Microchip Smart storage controllers */ #include "smartpqi_includes.h" +#include "smartpqi_controllers.h" CTASSERT(BSD_SUCCESS == PQI_STATUS_SUCCESS); /* - * Supported devices - */ -struct pqi_ident -{ - u_int16_t vendor; - u_int16_t device; - u_int16_t subvendor; - u_int16_t subdevice; - int hwif; - char *desc; -} pqi_identifiers[] = { - /* (MSCC PM8205 8x12G based) */ - {0x9005, 0x028f, 0x103c, 0x600, PQI_HWIF_SRCV, "P408i-p SR Gen10"}, - {0x9005, 0x028f, 0x103c, 0x601, PQI_HWIF_SRCV, "P408e-p SR Gen10"}, - {0x9005, 0x028f, 0x103c, 0x602, PQI_HWIF_SRCV, "P408i-a SR Gen10"}, - {0x9005, 0x028f, 0x103c, 0x603, PQI_HWIF_SRCV, "P408i-c SR Gen10"}, - {0x9005, 0x028f, 0x1028, 0x1FE0, PQI_HWIF_SRCV, "SmartRAID 3162-8i/eDell"}, - {0x9005, 0x028f, 0x9005, 0x608, PQI_HWIF_SRCV, "SmartRAID 3162-8i/e"}, - {0x9005, 0x028f, 0x103c, 0x609, PQI_HWIF_SRCV, "P408i-sb SR G10"}, - - /* (MSCC PM8225 8x12G based) */ - {0x9005, 0x028f, 0x103c, 0x650, PQI_HWIF_SRCV, "E208i-p SR Gen10"}, - {0x9005, 0x028f, 0x103c, 0x651, PQI_HWIF_SRCV, "E208e-p SR Gen10"}, - {0x9005, 0x028f, 0x103c, 0x652, PQI_HWIF_SRCV, "E208i-c SR Gen10"}, - {0x9005, 0x028f, 0x103c, 0x654, PQI_HWIF_SRCV, "E208i-a SR Gen10"}, - {0x9005, 0x028f, 0x103c, 0x655, PQI_HWIF_SRCV, "P408e-m SR Gen10"}, - {0x9005, 0x028f, 0x9005, 0x659, PQI_HWIF_SRCV, "2100C8iOXS"}, - - /* (MSCC PM8221 8x12G based) */ - {0x9005, 0x028f, 0x103c, 0x700, PQI_HWIF_SRCV, "P204i-c SR Gen10"}, - {0x9005, 0x028f, 0x103c, 0x701, PQI_HWIF_SRCV, "P204i-b SR Gen10"}, - {0x9005, 0x028f, 0x193d, 0x1104, PQI_HWIF_SRCV, "UN RAID P2404-Mf-4i-2GB"}, - {0x9005, 0x028f, 0x193d, 0x1106, PQI_HWIF_SRCV, "UN RAID P2404-Mf-4i-1GB"}, - {0x9005, 0x028f, 0x193d, 0x1108, PQI_HWIF_SRCV, "UN RAID P4408-Ma-8i-2GB"}, - {0x9005, 0x028f, 0x193d, 0x1109, PQI_HWIF_SRCV, "UN RAID P4408-Mr-8i-2GB"}, - - /* (MSCC PM8204 8x12G based) */ - {0x9005, 0x028f, 0x9005, 0x800, PQI_HWIF_SRCV, "SmartRAID 3154-8i"}, - {0x9005, 0x028f, 0x9005, 0x801, PQI_HWIF_SRCV, "SmartRAID 3152-8i"}, - {0x9005, 0x028f, 0x9005, 0x802, PQI_HWIF_SRCV, "SmartRAID 3151-4i"}, - {0x9005, 0x028f, 0x9005, 0x803, PQI_HWIF_SRCV, "SmartRAID 3101-4i"}, - {0x9005, 0x028f, 0x9005, 0x804, PQI_HWIF_SRCV, "SmartRAID 3154-8e"}, - {0x9005, 0x028f, 0x9005, 0x805, PQI_HWIF_SRCV, "SmartRAID 3102-8i"}, - {0x9005, 0x028f, 0x9005, 0x806, PQI_HWIF_SRCV, "SmartRAID 3100"}, - {0x9005, 0x028f, 0x9005, 0x807, PQI_HWIF_SRCV, "SmartRAID 3162-8i"}, - {0x9005, 0x028f, 0x152d, 0x8a22, PQI_HWIF_SRCV, "QS-8204-8i"}, - {0x9005, 0x028f, 0x193d, 0xf460, PQI_HWIF_SRCV, "UN RAID P460-M4"}, - {0x9005, 0x028f, 0x193d, 0xf461, PQI_HWIF_SRCV, "UN RAID P460-B4"}, - {0x9005, 0x028f, 0x1bd4, 0x004b, PQI_HWIF_SRCV, "PM8204-2GB"}, - {0x9005, 0x028f, 0x1bd4, 0x004c, PQI_HWIF_SRCV, "PM8204-4GB"}, - {0x9005, 0x028f, 0x193d, 0x1105, PQI_HWIF_SRCV, "UN RAID P4408-Mf-8i-2GB"}, - {0x9005, 0x028f, 0x193d, 0x1107, PQI_HWIF_SRCV, "UN RAID P4408-Mf-8i-4GB"}, - {0x9005, 0x028f, 0x1d8d, 0x800, PQI_HWIF_SRCV, "Fiberhome SmartRAID AIS-8204-8i"}, - {0x9005, 0x028f, 0x9005, 0x0808, PQI_HWIF_SRCV, "SmartRAID 3101E-4i"}, - {0x9005, 0x028f, 0x9005, 0x0809, PQI_HWIF_SRCV, "SmartRAID 3102E-8i"}, - {0x9005, 0x028f, 0x9005, 0x080a, PQI_HWIF_SRCV, "SmartRAID 3152-8i/N"}, - {0x9005, 0x028f, 0x1cc4, 0x0101, PQI_HWIF_SRCV, "Ramaxel FBGF-RAD PM8204"}, - - /* (MSCC PM8222 8x12G based) */ - {0x9005, 0x028f, 0x9005, 0x900, PQI_HWIF_SRCV, "SmartHBA 2100-8i"}, - {0x9005, 0x028f, 0x9005, 0x901, PQI_HWIF_SRCV, "SmartHBA 2100-4i"}, - {0x9005, 0x028f, 0x9005, 0x902, PQI_HWIF_SRCV, "HBA 1100-8i"}, - {0x9005, 0x028f, 0x9005, 0x903, PQI_HWIF_SRCV, "HBA 1100-4i"}, - {0x9005, 0x028f, 0x9005, 0x904, PQI_HWIF_SRCV, "SmartHBA 2100-8e"}, - {0x9005, 0x028f, 0x9005, 0x905, PQI_HWIF_SRCV, "HBA 1100-8e"}, - {0x9005, 0x028f, 0x9005, 0x906, PQI_HWIF_SRCV, "SmartHBA 2100-4i4e"}, - {0x9005, 0x028f, 0x9005, 0x907, PQI_HWIF_SRCV, "HBA 1100"}, - {0x9005, 0x028f, 0x9005, 0x908, PQI_HWIF_SRCV, "SmartHBA 2100"}, - {0x9005, 0x028f, 0x9005, 0x90a, PQI_HWIF_SRCV, "SmartHBA 2100A-8i"}, - {0x9005, 0x028f, 0x193d, 0x8460, PQI_HWIF_SRCV, "UN HBA H460-M1"}, - {0x9005, 0x028f, 0x193d, 0x8461, PQI_HWIF_SRCV, "UN HBA H460-B1"}, - {0x9005, 0x028f, 0x193d, 0xc460, PQI_HWIF_SRCV, "UN RAID P460-M2"}, - {0x9005, 0x028f, 0x193d, 0xc461, PQI_HWIF_SRCV, "UN RAID P460-B2"}, - {0x9005, 0x028f, 0x1bd4, 0x004a, PQI_HWIF_SRCV, "PM8222-SHBA"}, - {0x9005, 0x028f, 0x13fe, 0x8312, PQI_HWIF_SRCV, "MIC-8312BridgeB"}, - {0x9005, 0x028f, 0x1bd4, 0x004f, PQI_HWIF_SRCV, "PM8222-HBA"}, - {0x9005, 0x028f, 0x1d8d, 0x908, PQI_HWIF_SRCV, "Fiberhome SmartHBA AIS-8222-8i"}, - {0x9005, 0x028f, 0x1bd4, 0x006C, PQI_HWIF_SRCV, "RS0800M5E8i"}, - {0x9005, 0x028f, 0x1bd4, 0x006D, PQI_HWIF_SRCV, "RS0800M5H8i"}, - {0x9005, 0x028f, 0x1cc4, 0x0201, PQI_HWIF_SRCV, "Ramaxel FBGF-RAD PM8222"}, - - /* (SRCx MSCC FVB 24x12G based) */ - {0x9005, 0x028f, 0x103c, 0x1001, PQI_HWIF_SRCV, "MSCC FVB"}, - - /* (MSCC PM8241 24x12G based) */ - - /* (MSCC PM8242 24x12G based) */ - {0x9005, 0x028f, 0x152d, 0x8a37, PQI_HWIF_SRCV, "QS-8242-24i"}, - {0x9005, 0x028f, 0x9005, 0x1300, PQI_HWIF_SRCV, "HBA 1100-8i8e"}, - {0x9005, 0x028f, 0x9005, 0x1301, PQI_HWIF_SRCV, "HBA 1100-24i"}, - {0x9005, 0x028f, 0x9005, 0x1302, PQI_HWIF_SRCV, "SmartHBA 2100-8i8e"}, - {0x9005, 0x028f, 0x9005, 0x1303, PQI_HWIF_SRCV, "SmartHBA 2100-24i"}, - {0x9005, 0x028f, 0x105b, 0x1321, PQI_HWIF_SRCV, "8242-24i"}, - {0x9005, 0x028f, 0x1bd4, 0x0045, PQI_HWIF_SRCV, "SMART-HBA 8242-24i"}, - {0x9005, 0x028f, 0x1bd4, 0x006B, PQI_HWIF_SRCV, "RS0800M5H24i"}, - {0x9005, 0x028f, 0x1bd4, 0x0070, PQI_HWIF_SRCV, "RS0800M5E24i"}, - - /* (MSCC PM8236 16x12G based) */ - {0x9005, 0x028f, 0x152d, 0x8a24, PQI_HWIF_SRCV, "QS-8236-16i"}, - {0x9005, 0x028f, 0x9005, 0x1380, PQI_HWIF_SRCV, "SmartRAID 3154-16i"}, - {0x9005, 0x028f, 0x1bd4, 0x0046, PQI_HWIF_SRCV, "RAID 8236-16i"}, - {0x9005, 0x028f, 0x1d8d, 0x806, PQI_HWIF_SRCV, "Fiberhome SmartRAID AIS-8236-16i"}, - {0x9005, 0x028f, 0x1cf2, 0x0B27, PQI_HWIF_SRCV, "ZTE SmartROC3100 SDPSA/B-18i 4G"}, - {0x9005, 0x028f, 0x1cf2, 0x0B45, PQI_HWIF_SRCV, "ZTE SmartROC3100 SDPSA/B_L-18i 2G"}, - {0x9005, 0x028f, 0x1cf2, 0x5445, PQI_HWIF_SRCV, "ZTE SmartROC3100 RM241-18i 2G"}, - {0x9005, 0x028f, 0x1cf2, 0x5446, PQI_HWIF_SRCV, "ZTE SmartROC3100 RM242-18i 4G"}, - {0x9005, 0x028f, 0x1cf2, 0x5449, PQI_HWIF_SRCV, "ZTE SmartROC3100 RS241-18i 2G"}, - {0x9005, 0x028f, 0x1cf2, 0x544A, PQI_HWIF_SRCV, "ZTE SmartROC3100 RS242-18i 4G"}, - {0x9005, 0x028f, 0x1cf2, 0x544D, PQI_HWIF_SRCV, "ZTE SmartROC3100 RM241B-18i 2G"}, - {0x9005, 0x028f, 0x1cf2, 0x544E, PQI_HWIF_SRCV, "ZTE SmartROC3100 RM242B-18i 4G"}, - {0x9005, 0x028f, 0x1bd4, 0x006F, PQI_HWIF_SRCV, "RS0804M5R16i"}, - - - - /* (MSCC PM8237 24x12G based) */ - {0x9005, 0x028f, 0x103c, 0x1100, PQI_HWIF_SRCV, "P816i-a SR Gen10"}, - {0x9005, 0x028f, 0x103c, 0x1101, PQI_HWIF_SRCV, "P416ie-m SR G10"}, - - /* (MSCC PM8238 16x12G based) */ - {0x9005, 0x028f, 0x152d, 0x8a23, PQI_HWIF_SRCV, "QS-8238-16i"}, - {0x9005, 0x028f, 0x9005, 0x1280, PQI_HWIF_SRCV, "HBA 1100-16i"}, - {0x9005, 0x028f, 0x9005, 0x1281, PQI_HWIF_SRCV, "HBA 1100-16e"}, - {0x9005, 0x028f, 0x105b, 0x1211, PQI_HWIF_SRCV, "8238-16i"}, - {0x9005, 0x028f, 0x1bd4, 0x0048, PQI_HWIF_SRCV, "SMART-HBA 8238-16i"}, - {0x9005, 0x028f, 0x9005, 0x1282, PQI_HWIF_SRCV, "SmartHBA 2100-16i"}, - {0x9005, 0x028f, 0x1d8d, 0x916, PQI_HWIF_SRCV, "Fiberhome SmartHBA AIS-8238-16i"}, - {0x9005, 0x028f, 0x1458, 0x1000, PQI_HWIF_SRCV, "GIGABYTE SmartHBA CLN1832"}, - {0x9005, 0x028f, 0x1cf2, 0x0B29, PQI_HWIF_SRCV, "ZTE SmartIOC2100 SDPSA/B_I-18i"}, - {0x9005, 0x028f, 0x1cf2, 0x5447, PQI_HWIF_SRCV, "ZTE SmartIOC2100 RM243-18i"}, - {0x9005, 0x028f, 0x1cf2, 0x544B, PQI_HWIF_SRCV, "ZTE SmartIOC2100 RS243-18i"}, - {0x9005, 0x028f, 0x1cf2, 0x544F, PQI_HWIF_SRCV, "ZTE SmartIOC2100 RM243B-18i"}, - {0x9005, 0x028f, 0x1bd4, 0x0071, PQI_HWIF_SRCV, "RS0800M5H16i"}, - {0x9005, 0x028f, 0x1bd4, 0x0072, PQI_HWIF_SRCV, "RS0800M5E16i"}, - - /* (MSCC PM8240 24x12G based) */ - {0x9005, 0x028f, 0x152d, 0x8a36, PQI_HWIF_SRCV, "QS-8240-24i"}, - {0x9005, 0x028f, 0x9005, 0x1200, PQI_HWIF_SRCV, "SmartRAID 3154-24i"}, - {0x9005, 0x028f, 0x9005, 0x1201, PQI_HWIF_SRCV, "SmartRAID 3154-8i16e"}, - {0x9005, 0x028f, 0x9005, 0x1202, PQI_HWIF_SRCV, "SmartRAID 3154-8i8e"}, - {0x9005, 0x028f, 0x1bd4, 0x0047, PQI_HWIF_SRCV, "RAID 8240-24i"}, - {0x9005, 0x028f, 0x1dfc, 0x3161, PQI_HWIF_SRCV, "NTCOM SAS3 RAID-24i"}, - {0x9005, 0x028f, 0x1F0C, 0x3161, PQI_HWIF_SRCV, "NT RAID 3100-24i"}, - - /* Huawei ID's */ - {0x9005, 0x028f, 0x19e5, 0xd227, PQI_HWIF_SRCV, "SR465C-M 4G"}, - {0x9005, 0x028f, 0x19e5, 0xd22a, PQI_HWIF_SRCV, "SR765-M"}, - {0x9005, 0x028f, 0x19e5, 0xd228, PQI_HWIF_SRCV, "SR455C-M 2G"}, - {0x9005, 0x028f, 0x19e5, 0xd22c, PQI_HWIF_SRCV, "SR455C-M 4G"}, - {0x9005, 0x028f, 0x19e5, 0xd229, PQI_HWIF_SRCV, "SR155-M"}, - {0x9005, 0x028f, 0x19e5, 0xd22b, PQI_HWIF_SRCV, "SR455C-ME 4G"}, - - /* (MSCC PM8252 8x12G based) */ - {0x9005, 0x028f, 0x193d, 0x110b, PQI_HWIF_SRCV, "UN HBA H4508-Mf-8i"}, - {0x9005, 0x028f, 0x1bd4, 0x0052, PQI_HWIF_SRCV, "MT0801M6E"}, - {0x9005, 0x028f, 0x1bd4, 0x0054, PQI_HWIF_SRCV, "MT0800M6H"}, - {0x9005, 0x028f, 0x1bd4, 0x0086, PQI_HWIF_SRCV, "RT0800M7E"}, - {0x9005, 0x028f, 0x1bd4, 0x0087, PQI_HWIF_SRCV, "RT0800M7H"}, - {0x9005, 0x028f, 0x1f51, 0x1001, PQI_HWIF_SRCV, "SmartHBA P6600-8i"}, - {0x9005, 0x028f, 0x1f51, 0x1003, PQI_HWIF_SRCV, "SmartHBA P6600-8e"}, - {0x9005, 0x028f, 0x9005, 0x1460, PQI_HWIF_SRCV, "HBA 1200"}, - {0x9005, 0x028f, 0x9005, 0x1461, PQI_HWIF_SRCV, "SmartHBA 2200"}, - {0x9005, 0x028f, 0x9005, 0x1462, PQI_HWIF_SRCV, "HBA 1200-8i"}, - - /* (MSCC PM8254 32x12G based) */ - {0x9005, 0x028f, 0x1bd4, 0x0051, PQI_HWIF_SRCV, "MT0804M6R"}, - {0x9005, 0x028f, 0x1bd4, 0x0053, PQI_HWIF_SRCV, "MT0808M6R"}, - {0x9005, 0x028f, 0x1bd4, 0x0088, PQI_HWIF_SRCV, "RT0804M7R"}, - {0x9005, 0x028f, 0x1bd4, 0x0089, PQI_HWIF_SRCV, "RT0808M7R"}, - {0x9005, 0x028f, 0x1f51, 0x1002, PQI_HWIF_SRCV, "SmartRAID P7604-8i"}, - {0x9005, 0x028f, 0x1f51, 0x1004, PQI_HWIF_SRCV, "SmartRAID P7604-8e"}, - {0x9005, 0x028f, 0x9005, 0x14a0, PQI_HWIF_SRCV, "SmartRAID 3254-8i"}, - {0x9005, 0x028f, 0x9005, 0x14a1, PQI_HWIF_SRCV, "SmartRAID 3204-8i"}, - {0x9005, 0x028f, 0x9005, 0x14a2, PQI_HWIF_SRCV, "SmartRAID 3252-8i"}, - {0x9005, 0x028f, 0x9005, 0x14a4, PQI_HWIF_SRCV, "SmartRAID 3254-8i /e"}, - {0x9005, 0x028f, 0x9005, 0x14a5, PQI_HWIF_SRCV, "SmartRAID 3252-8i /e"}, - {0x9005, 0x028f, 0x9005, 0x14a6, PQI_HWIF_SRCV, "SmartRAID 3204-8i /e"}, - - /* (MSCC PM8262 16x12G based) */ - {0x9005, 0x028f, 0x9005, 0x14c0, PQI_HWIF_SRCV, "SmartHBA 2200-16i"}, - {0x9005, 0x028f, 0x9005, 0x14c1, PQI_HWIF_SRCV, "HBA 1200-16i"}, - {0x9005, 0x028f, 0x9005, 0x14c3, PQI_HWIF_SRCV, "HBA 1200-16e"}, - {0x9005, 0x028f, 0x9005, 0x14c4, PQI_HWIF_SRCV, "HBA 1200-8e"}, - {0x9005, 0x028f, 0x1f51, 0x1005, PQI_HWIF_SRCV, "SmartHBA P6600-16i"}, - {0x9005, 0x028f, 0x1f51, 0x1007, PQI_HWIF_SRCV, "SmartHBA P6600-8i8e"}, - {0x9005, 0x028f, 0x1f51, 0x1009, PQI_HWIF_SRCV, "SmartHBA P6600-16e"}, - {0x9005, 0x028f, 0x1cf2, 0x54dc, PQI_HWIF_SRCV, "ZTE SmartIOC2200 RM346-16i"}, - {0x9005, 0x028f, 0x1cf2, 0x0806, PQI_HWIF_SRCV, "ZTE SmartIOC2200 RS346-16i"}, - - /* (MSCC PM8264 16x12G based) */ - {0x9005, 0x028f, 0x9005, 0x14b0, PQI_HWIF_SRCV, "SmartRAID 3254-16i"}, - {0x9005, 0x028f, 0x9005, 0x14b1, PQI_HWIF_SRCV, "SmartRAID 3258-16i"}, - {0x9005, 0x028f, 0x1f51, 0x1006, PQI_HWIF_SRCV, "SmartRAID P7608-16i"}, - {0x9005, 0x028f, 0x1f51, 0x1008, PQI_HWIF_SRCV, "SmartRAID P7608-8i8e"}, - {0x9005, 0x028f, 0x1f51, 0x100a, PQI_HWIF_SRCV, "SmartRAID P7608-16e"}, - {0x9005, 0x028f, 0x1cf2, 0x54da, PQI_HWIF_SRCV, "ZTE SmartROC3200 RM344-16i 4G"}, - {0x9005, 0x028f, 0x1cf2, 0x54db, PQI_HWIF_SRCV, "ZTE SmartROC3200 RM345-16i 8G"}, - {0x9005, 0x028f, 0x1cf2, 0x0804, PQI_HWIF_SRCV, "ZTE SmartROC3200 RS344-16i 4G"}, - {0x9005, 0x028f, 0x1cf2, 0x0805, PQI_HWIF_SRCV, "ZTE SmartROC3200 RS345-16i 8G"}, - - /* (MSCC PM8265 16x12G based) */ - {0x9005, 0x028f, 0x1590, 0x02dc, PQI_HWIF_SRCV, "SR416i-a Gen10+"}, - {0x9005, 0x028f, 0x9005, 0x1470, PQI_HWIF_SRCV, "SmartRAID 3200"}, - {0x9005, 0x028f, 0x9005, 0x1471, PQI_HWIF_SRCV, "SmartRAID 3254-16i /e"}, - {0x9005, 0x028f, 0x9005, 0x1472, PQI_HWIF_SRCV, "SmartRAID 3258-16i /e"}, - {0x9005, 0x028f, 0x9005, 0x1473, PQI_HWIF_SRCV, "SmartRAID 3284-16io /e/uC"}, - {0x9005, 0x028f, 0x9005, 0x1474, PQI_HWIF_SRCV, "SmartRAID 3254-16io /e"}, - {0x9005, 0x028f, 0x9005, 0x1475, PQI_HWIF_SRCV, "SmartRAID 3254-16e /e"}, - - /* (MSCC PM8266 16x12G based) */ - {0x9005, 0x028f, 0x1014, 0x0718, PQI_HWIF_SRCV, "IBM 4-Port 24G SAS"}, - {0x9005, 0x028f, 0x9005, 0x1490, PQI_HWIF_SRCV, "HBA 1200p Ultra"}, - {0x9005, 0x028f, 0x9005, 0x1491, PQI_HWIF_SRCV, "SmartHBA 2200p Ultra"}, - {0x9005, 0x028f, 0x9005, 0x1402, PQI_HWIF_SRCV, "HBA Ultra 1200P-16i"}, - {0x9005, 0x028f, 0x9005, 0x1441, PQI_HWIF_SRCV, "HBA Ultra 1200P-32i"}, - - /* (MSCC PM8268 16x12G based) */ - {0x9005, 0x028f, 0x9005, 0x14d0, PQI_HWIF_SRCV, "SmartRAID Ultra 3258P-16i"}, - - /* (MSCC PM8269 16x12G based) */ - {0x9005, 0x028f, 0x9005, 0x1400, PQI_HWIF_SRCV, "SmartRAID Ultra 3258P-16i /e"}, - - /* (MSCC PM8270 16x12G based) */ - {0x9005, 0x028f, 0x9005, 0x1410, PQI_HWIF_SRCV, "HBA Ultra 1200P-16e"}, - {0x9005, 0x028f, 0x9005, 0x1411, PQI_HWIF_SRCV, "HBA 1200 Ultra"}, - {0x9005, 0x028f, 0x9005, 0x1412, PQI_HWIF_SRCV, "SmartHBA 2200 Ultra"}, - {0x9005, 0x028f, 0x9005, 0x1463, PQI_HWIF_SRCV, "SmartHBA 2200-8io /e"}, - {0x9005, 0x028f, 0x9005, 0x14c2, PQI_HWIF_SRCV, "SmartHBA 2200-16io /e"}, - - /* (MSCC PM8271 16x12G based) */ - {0x9005, 0x028f, 0x9005, 0x14e0, PQI_HWIF_SRCV, "SmartIOC PM8271"}, - - /* (MSCC PM8272 16x12G based) */ - {0x9005, 0x028f, 0x9005, 0x1420, PQI_HWIF_SRCV, "SmartRAID Ultra 3254-16e"}, - - /* (MSCC PM8273 16x12G based) */ - {0x9005, 0x028f, 0x9005, 0x1430, PQI_HWIF_SRCV, "SmartRAID Ultra 3254-16e /e"}, - - /* (MSCC PM8274 16x12G based) */ - {0x9005, 0x028f, 0x1e93, 0x1000, PQI_HWIF_SRCV, "ByteHBA JGH43024-8"}, - {0x9005, 0x028f, 0x1e93, 0x1001, PQI_HWIF_SRCV, "ByteHBA JGH43034-8"}, - {0x9005, 0x028f, 0x1e93, 0x1005, PQI_HWIF_SRCV, "ByteHBA JGH43014-8"}, - - /* (MSCC PM8275 16x12G based) */ - {0x9005, 0x028f, 0x9005, 0x14f0, PQI_HWIF_SRCV, "SmartIOC PM8275"}, - - /* (MSCC PM8276 16x12G based) */ - {0x9005, 0x028f, 0x9005, 0x1480, PQI_HWIF_SRCV, "SmartRAID 3200 Ultra"}, - {0x9005, 0x028f, 0x1e93, 0x1002, PQI_HWIF_SRCV, "ByteHBA JGH44014-8"}, - - /* (MSCC PM8278 16x12G based) */ - {0x9005, 0x028f, 0x9005, 0x1440, PQI_HWIF_SRCV, "SmartRAID Ultra 3258P-32i"}, - - /* (MSCC PM8279 32x12G based) */ - {0x9005, 0x028f, 0x9005, 0x1450, PQI_HWIF_SRCV, "SmartRAID Ultra 3258P-32i /e"}, - {0x9005, 0x028f, 0x1590, 0x0294, PQI_HWIF_SRCV, "SR932i-p Gen10+"}, - {0x9005, 0x028f, 0x1590, 0x0381, PQI_HWIF_SRCV, "SR932i-p Gen11"}, - {0x9005, 0x028f, 0x1590, 0x0382, PQI_HWIF_SRCV, "SR308i-p Gen11"}, - {0x9005, 0x028f, 0x1590, 0x0383, PQI_HWIF_SRCV, "SR308i-o Gen11"}, - {0x9005, 0x028f, 0x1590, 0x02db, PQI_HWIF_SRCV, "SR416ie-m Gen11"}, - {0x9005, 0x028f, 0x1590, 0x032e, PQI_HWIF_SRCV, "SR416i-o Gen11"}, - {0x9005, 0x028f, 0x9005, 0x1452, PQI_HWIF_SRCV, "SmartRAID 3200p Ultra"}, - - /* (MSCC HBA/SMARTHBA/CFF SmartRAID - Lenovo 8X12G 16X12G based) */ - {0x9005, 0x028f, 0x1d49, 0x0220, PQI_HWIF_SRCV, "4350-8i SAS/SATA HBA"}, - {0x9005, 0x028f, 0x1d49, 0x0221, PQI_HWIF_SRCV, "4350-16i SAS/SATA HBA"}, - {0x9005, 0x028f, 0x1d49, 0x0520, PQI_HWIF_SRCV, "5350-8i"}, - {0x9005, 0x028f, 0x1d49, 0x0522, PQI_HWIF_SRCV, "5350-8i INTR"}, - {0x9005, 0x028f, 0x1d49, 0x0620, PQI_HWIF_SRCV, "9350-8i 2GB Flash"}, - {0x9005, 0x028f, 0x1d49, 0x0621, PQI_HWIF_SRCV, "9350-8i 2GB Flash INTR"}, - {0x9005, 0x028f, 0x1d49, 0x0622, PQI_HWIF_SRCV, "9350-16i 4GB Flash"}, - {0x9005, 0x028f, 0x1d49, 0x0623, PQI_HWIF_SRCV, "9350-16i 4GB Flash INTR"}, - - {0, 0, 0, 0, 0, 0} -}; - -struct pqi_ident -pqi_family_identifiers[] = { - {0x9005, 0x028f, 0, 0, PQI_HWIF_SRCV, "Smart Array Storage Controller"}, - {0, 0, 0, 0, 0, 0} -}; + * Logging levels global +*/ +unsigned long logging_level = PQISRC_LOG_LEVEL; /* * Function to identify the installed adapter. @@ -404,10 +128,12 @@ static void read_device_hint_resource(struct pqisrc_softstate *softs, { DBG_FUNC("IN\n"); + long result = 0; + device_t dev = softs->os_specific.pqi_dev; - if (resource_long_value("smartpqi", device_get_unit(dev), keyword, (long *)value) == DEVICE_HINT_SUCCESS) { - if (*value) { + if (resource_long_value("smartpqi", device_get_unit(dev), keyword, &result) == DEVICE_HINT_SUCCESS) { + if (result) { /* set resource to 1 for disabling the * firmware feature in device hint file. */ *value = 0; @@ -434,11 +160,14 @@ static void read_device_hint_decimal_value(struct pqisrc_softstate *softs, { DBG_FUNC("IN\n"); + long result = 0; + device_t dev = softs->os_specific.pqi_dev; - if (resource_long_value("smartpqi", device_get_unit(dev), keyword, (long *)value) == DEVICE_HINT_SUCCESS) { + if (resource_long_value("smartpqi", device_get_unit(dev), keyword, &result) == DEVICE_HINT_SUCCESS) { /* Nothing to do here. Value reads * directly from Device.Hint file */ + *value = result; } else { /* Set to max to determine the value */ @@ -482,13 +211,23 @@ static void smartpqi_read_all_device_hint_file_entries(struct pqisrc_softstate * read_device_hint_decimal_value(softs, SCATTER_GATHER_COUNT, &value); softs->hint.sg_segments = value; - /* hint.smartpqi.0.queue_count = "0" */ - read_device_hint_decimal_value(softs, QUEUE_COUNT, &value); - softs->hint.cpu_count = value; - DBG_FUNC("IN\n"); } +/* Get the driver parameter tunables. */ +static void +smartpqi_get_tunables(void) +{ + /* + * Temp variable used to get the value from loader.conf. + * Initializing it with the current logging level value. + */ + unsigned long logging_level_temp = PQISRC_LOG_LEVEL; + + TUNABLE_ULONG_FETCH("hw.smartpqi.debug_level", &logging_level_temp); + + DBG_SET_LOGGING_LEVEL(logging_level_temp); +} /* * Allocate resources for our device, set up the bus interface. @@ -506,7 +245,7 @@ smartpqi_attach(device_t dev) rcb_t *rcbp = NULL; /* - * Initialise softc. + * Initialize softc. */ softs = device_get_softc(dev); @@ -518,6 +257,8 @@ smartpqi_attach(device_t dev) memset(softs, 0, sizeof(*softs)); softs->os_specific.pqi_dev = dev; + smartpqi_get_tunables(); + DBG_FUNC("IN\n"); /* assume failure is 'not configured' */ @@ -820,7 +561,7 @@ static device_method_t pqi_methods[] = { DEVMETHOD(device_suspend, smartpqi_suspend), DEVMETHOD(device_resume, smartpqi_resume), DEVMETHOD(device_shutdown, smartpqi_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t smartpqi_pci_driver = { @@ -830,4 +571,5 @@ static driver_t smartpqi_pci_driver = { }; DRIVER_MODULE(smartpqi, pci, smartpqi_pci_driver, 0, 0); + MODULE_DEPEND(smartpqi, pci, 1, 1, 1); diff --git a/sys/dev/smartpqi/smartpqi_mem.c b/sys/dev/smartpqi/smartpqi_mem.c index 239d619968d2..08f806681dce 100644 --- a/sys/dev/smartpqi/smartpqi_mem.c +++ b/sys/dev/smartpqi/smartpqi_mem.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/dev/smartpqi/smartpqi_misc.c b/sys/dev/smartpqi/smartpqi_misc.c index 20ba4fc11eb7..6db0d80ed993 100644 --- a/sys/dev/smartpqi/smartpqi_misc.c +++ b/sys/dev/smartpqi/smartpqi_misc.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -58,7 +58,7 @@ void os_wellness_periodic(void *data) { struct pqisrc_softstate *softs = (struct pqisrc_softstate *)data; - int ret = 0; + int ret; /* update time to FW */ if (!pqisrc_ctrl_offline(softs)){ @@ -286,27 +286,3 @@ bsd_set_hint_adapter_cap(struct pqisrc_softstate *softs) DBG_FUNC("OUT\n"); } - -void -bsd_set_hint_adapter_cpu_config(struct pqisrc_softstate *softs) -{ - DBG_FUNC("IN\n"); - - /* online cpu count decides the no.of queues the driver can create, - * and msi interrupt count as well. - * If the cpu count is "zero" set by hint file then the driver - * can have "one" queue and "one" legacy interrupt. (It shares event queue for - * operational IB queue). - * Check for os_get_intr_config function for interrupt assignment.*/ - - if (softs->hint.cpu_count > softs->num_cpus_online) { - /* Nothing to do here. Supported cpu count - * already fetched from hardware */ - } - else { - /* Set Device.Hint cpu count here */ - softs->num_cpus_online = softs->hint.cpu_count; - } - - DBG_FUNC("OUT\n"); -} diff --git a/sys/dev/smartpqi/smartpqi_prototypes.h b/sys/dev/smartpqi/smartpqi_prototypes.h index a10e5031d85e..7abce9c3789d 100644 --- a/sys/dev/smartpqi/smartpqi_prototypes.h +++ b/sys/dev/smartpqi/smartpqi_prototypes.h @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -84,23 +84,23 @@ uint32_t pqisrc_get_tag(lockless_stack_t *); /* smartpqi_discovery.c */ void pqisrc_remove_device(pqisrc_softstate_t *, pqi_scsi_dev_t *); boolean_t pqisrc_add_softs_entry(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device, - uint8_t *scsi3addr); + uint8_t const *scsi3addr); int pqisrc_get_ctrl_fw_version(pqisrc_softstate_t *); int pqisrc_rescan_devices(pqisrc_softstate_t *); int pqisrc_scan_devices(pqisrc_softstate_t *); void pqisrc_cleanup_devices(pqisrc_softstate_t *); void pqisrc_device_mem_free(pqisrc_softstate_t *, pqi_scsi_dev_t *); -boolean_t pqisrc_is_external_raid_device(pqi_scsi_dev_t *device); +boolean_t pqisrc_is_external_raid_device(pqi_scsi_dev_t const *device); void pqisrc_free_device(pqisrc_softstate_t * softs,pqi_scsi_dev_t *device); void pqisrc_init_bitmap(pqisrc_softstate_t *softs); void pqisrc_remove_target_bit(pqisrc_softstate_t *softs, int target); int pqisrc_find_avail_target(pqisrc_softstate_t *softs); int pqisrc_find_device_list_index(pqisrc_softstate_t *softs, - pqi_scsi_dev_t *device); + pqi_scsi_dev_t const *device); int pqisrc_find_btl_list_index(pqisrc_softstate_t *softs, int bus, int target, int lun); int pqisrc_delete_softs_entry(pqisrc_softstate_t *softs, - pqi_scsi_dev_t *device); + pqi_scsi_dev_t const *device); int pqisrc_get_physical_logical_luns(pqisrc_softstate_t *softs, uint8_t cmd, reportlun_data_ext_t **buff, size_t *data_length); int pqisrc_send_scsi_inquiry(pqisrc_softstate_t *softs, @@ -112,16 +112,16 @@ int pqisrc_prepare_send_raid(pqisrc_softstate_t *, pqisrc_raid_req_t *, /* smartpqi_helper.c */ -boolean_t pqisrc_ctrl_offline(pqisrc_softstate_t *); +boolean_t pqisrc_ctrl_offline(pqisrc_softstate_t const *); void pqisrc_heartbeat_timer_handler(pqisrc_softstate_t *); int pqisrc_wait_on_condition(pqisrc_softstate_t *softs, rcb_t *rcb, uint32_t timeout); -boolean_t pqisrc_device_equal(pqi_scsi_dev_t *, pqi_scsi_dev_t *); -boolean_t pqisrc_is_hba_lunid(uint8_t *); -boolean_t pqisrc_is_logical_device(pqi_scsi_dev_t *); +boolean_t pqisrc_device_equal(pqi_scsi_dev_t const *, pqi_scsi_dev_t const *); +boolean_t pqisrc_is_hba_lunid(uint8_t const*); +boolean_t pqisrc_is_logical_device(pqi_scsi_dev_t const *); void pqisrc_sanitize_inquiry_string(unsigned char *, int ); -void pqisrc_display_device_info(pqisrc_softstate_t *, char *, pqi_scsi_dev_t *); -boolean_t pqisrc_scsi3addr_equal(uint8_t *, uint8_t *); +void pqisrc_display_device_info(pqisrc_softstate_t *, char const *, pqi_scsi_dev_t *); +boolean_t pqisrc_scsi3addr_equal(uint8_t const *, uint8_t const *); void check_struct_sizes(void); char *pqisrc_raidlevel_to_string(uint8_t); void pqisrc_configure_legacy_intx(pqisrc_softstate_t*, boolean_t); @@ -151,7 +151,7 @@ void pqisrc_show_aio_error_info(pqisrc_softstate_t *softs, rcb_t *rcb, aio_path_error_info_elem_t *aio_err); void pqisrc_show_raid_error_info(pqisrc_softstate_t *softs, rcb_t *rcb, raid_path_error_info_elem_t *aio_err); -boolean_t suppress_innocuous_error_prints(pqisrc_softstate_t *softs, +boolean_t suppress_innocuous_error_prints(pqisrc_softstate_t const *softs, rcb_t *rcb); uint8_t pqisrc_get_cmd_from_rcb(rcb_t *); boolean_t pqisrc_is_innocuous_error(pqisrc_softstate_t *, rcb_t *, void *); @@ -163,7 +163,7 @@ int pqisrc_build_send_vendor_request(pqisrc_softstate_t *softs, int pqisrc_build_send_io(pqisrc_softstate_t *,rcb_t *); int pqisrc_build_scsi_cmd_raidbypass(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device, rcb_t *rcb); -int pqisrc_send_tmf(pqisrc_softstate_t *, pqi_scsi_dev_t *, +int pqisrc_send_tmf(pqisrc_softstate_t *, pqi_scsi_dev_t const *, rcb_t *, rcb_t *, int); int pqisrc_write_current_time_to_host_wellness(pqisrc_softstate_t *softs); int pqisrc_write_driver_version_to_host_wellness(pqisrc_softstate_t *softs); @@ -173,27 +173,26 @@ void pqisrc_build_aio_R1_write(pqisrc_softstate_t *, pqi_aio_raid1_write_req_t *, rcb_t *, uint32_t); void pqisrc_build_aio_R5or6_write(pqisrc_softstate_t *, pqi_aio_raid5or6_write_req_t *, rcb_t *, uint32_t); -void pqisrc_show_cdb(pqisrc_softstate_t *softs, char *msg, rcb_t *rcb, uint8_t *cdb); -void pqisrc_print_buffer(pqisrc_softstate_t *softs, char *msg, void *user_buf, uint32_t total_len, uint32_t flags); +void pqisrc_show_cdb(pqisrc_softstate_t *softs, char const *msg, rcb_t const *rcb, uint8_t *cdb); +void pqisrc_print_buffer(pqisrc_softstate_t *softs, char const *msg, void *user_buf, uint32_t total_len, uint32_t flags); void pqisrc_show_rcb_details(pqisrc_softstate_t *softs, rcb_t *rcb, char *msg, void *err_info); void pqisrc_show_aio_io(pqisrc_softstate_t *, rcb_t *, pqi_aio_req_t *, uint32_t); -void pqisrc_show_aio_common(pqisrc_softstate_t *, rcb_t *, pqi_aio_req_t *); -void pqisrc_show_aio_R1_write(pqisrc_softstate_t *, rcb_t *, +void pqisrc_show_aio_common(pqisrc_softstate_t *, rcb_t const *, pqi_aio_req_t *); +void pqisrc_show_aio_R1_write(pqisrc_softstate_t *, rcb_t const *, pqi_aio_raid1_write_req_t *); -void pqisrc_show_aio_R5or6_write(pqisrc_softstate_t *, rcb_t *, +void pqisrc_show_aio_R5or6_write(pqisrc_softstate_t *, rcb_t const *, pqi_aio_raid5or6_write_req_t *); -boolean_t pqisrc_cdb_is_write(uint8_t *); -void print_this_counter(pqisrc_softstate_t *softs, io_counters_t *pcounter, char *msg); +boolean_t pqisrc_cdb_is_write(uint8_t const *); +void print_this_counter(pqisrc_softstate_t const *softs, io_counters_t const *pcounter, char const *msg); void print_all_counters(pqisrc_softstate_t *softs, uint32_t flags); char *io_path_to_ascii(IO_PATH_T path); void int_to_scsilun(uint64_t, uint8_t *); -boolean_t pqisrc_cdb_is_read(uint8_t *); +boolean_t pqisrc_cdb_is_read(uint8_t const *); void pqisrc_build_aio_io(pqisrc_softstate_t *, rcb_t *, pqi_aio_req_t *, uint32_t); uint8_t pqisrc_get_aio_data_direction(rcb_t *); uint8_t pqisrc_get_raid_data_direction(rcb_t *); -void dump_tmf_details(pqisrc_softstate_t *, rcb_t *, char *); -io_type_t get_io_type_from_cdb(uint8_t *); +io_type_t get_io_type_from_cdb(uint8_t const *); OS_ATOMIC64_T increment_this_counter(io_counters_t *, IO_PATH_T , io_type_t ); boolean_t is_buffer_zero(void *, uint32_t ); @@ -237,7 +236,7 @@ int pqisrc_delete_op_queue(pqisrc_softstate_t *, uint32_t, boolean_t); void pqisrc_destroy_event_queue(pqisrc_softstate_t *); void pqisrc_destroy_op_ib_queues(pqisrc_softstate_t *); void pqisrc_destroy_op_ob_queues(pqisrc_softstate_t *); -int pqisrc_change_op_ibq_queue_prop(pqisrc_softstate_t *, ib_queue_t *, +int pqisrc_change_op_ibq_queue_prop(pqisrc_softstate_t *, ib_queue_t const *, uint32_t); int pqisrc_create_op_obq(pqisrc_softstate_t *, ob_queue_t *); int pqisrc_create_op_ibq(pqisrc_softstate_t *, ib_queue_t *); @@ -252,6 +251,7 @@ int pqisrc_process_task_management_response(pqisrc_softstate_t *, /* smartpqi_ioctl.c*/ int pqisrc_passthru_ioctl(struct pqisrc_softstate *, void *, int); +int pqisrc_big_passthru_ioctl(struct pqisrc_softstate *, void *, int); /* Functions Prototypes */ /* smartpqi_mem.c */ @@ -287,7 +287,6 @@ int os_destroy_semaphore(struct sema *); void os_sema_lock(struct sema *); void os_sema_unlock(struct sema *); void bsd_set_hint_adapter_cap(struct pqisrc_softstate *); -void bsd_set_hint_adapter_cpu_config(struct pqisrc_softstate *); int os_strlcpy(char *dst, char *src, int len); void os_complete_outstanding_cmds_nodevice(pqisrc_softstate_t *); diff --git a/sys/dev/smartpqi/smartpqi_queue.c b/sys/dev/smartpqi/smartpqi_queue.c index f05c951cd4f9..e8a467531aa4 100644 --- a/sys/dev/smartpqi/smartpqi_queue.c +++ b/sys/dev/smartpqi/smartpqi_queue.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -514,11 +514,7 @@ pqisrc_destroy_event_queue(pqisrc_softstate_t *softs) DBG_FUNC("IN\n"); if (softs->event_q.created == true) { - int ret = PQI_STATUS_SUCCESS; - ret = pqisrc_delete_op_queue(softs, softs->event_q.q_id, false); - if (ret) { - DBG_ERR("Failed to Delete Event Q %u\n", softs->event_q.q_id); - } + pqisrc_delete_op_queue(softs, softs->event_q.q_id, false); softs->event_q.created = false; } @@ -535,7 +531,7 @@ pqisrc_destroy_event_queue(pqisrc_softstate_t *softs) void pqisrc_destroy_op_ib_queues(pqisrc_softstate_t *softs) { - int ret = PQI_STATUS_SUCCESS; + ib_queue_t *op_ib_q = NULL; uint32_t total_op_ibq = softs->num_op_raid_ibq; int i; @@ -548,12 +544,7 @@ pqisrc_destroy_op_ib_queues(pqisrc_softstate_t *softs) op_ib_q = &softs->op_raid_ib_q[i]; release_queue: if (op_ib_q->created == true) { - ret = pqisrc_delete_op_queue(softs, op_ib_q->q_id, - true); - if (ret) { - DBG_ERR("Failed to Delete IB Q %u\n", - op_ib_q->q_id); - } + pqisrc_delete_op_queue(softs, op_ib_q->q_id, true); op_ib_q->created = false; } @@ -582,7 +573,6 @@ release_queue: void pqisrc_destroy_op_ob_queues(pqisrc_softstate_t *softs) { - int ret = PQI_STATUS_SUCCESS; int i; ob_queue_t *op_ob_q = NULL; @@ -592,10 +582,7 @@ pqisrc_destroy_op_ob_queues(pqisrc_softstate_t *softs) op_ob_q = &softs->op_ob_q[i]; if (op_ob_q->created == true) { - ret = pqisrc_delete_op_queue(softs, op_ob_q->q_id, false); - if (ret) { - DBG_ERR("Failed to Delete OB Q %u\n",op_ob_q->q_id); - } + pqisrc_delete_op_queue(softs, op_ob_q->q_id, false); op_ob_q->created = false; } @@ -643,7 +630,7 @@ pqisrc_destroy_admin_queue(pqisrc_softstate_t *softs) */ int pqisrc_change_op_ibq_queue_prop(pqisrc_softstate_t *softs, - ib_queue_t *op_ib_q, uint32_t prop) + ib_queue_t const *op_ib_q, uint32_t prop) { int ret = PQI_STATUS_SUCCESS; gen_adm_req_iu_t admin_req; @@ -701,7 +688,7 @@ pqisrc_create_op_obq(pqisrc_softstate_t *softs, int i = 0; DBG_WARN("Error Status Descriptors\n"); for (i = 0; i < 4; i++) - DBG_WARN(" %x ",admin_resp.resp_type.create_op_oq.status_desc[i]); + DBG_WARN(" %x\n",admin_resp.resp_type.create_op_oq.status_desc[i]); } DBG_FUNC("OUT ret : %d\n", ret); @@ -744,7 +731,7 @@ pqisrc_create_op_ibq(pqisrc_softstate_t *softs, int i = 0; DBG_WARN("Error Status Decsriptors\n"); for (i = 0; i < 4; i++) - DBG_WARN(" %x ",admin_resp.resp_type.create_op_iq.status_desc[i]); + DBG_WARN(" %x\n",admin_resp.resp_type.create_op_iq.status_desc[i]); } DBG_FUNC("OUT ret : %d\n", ret); diff --git a/sys/dev/smartpqi/smartpqi_request.c b/sys/dev/smartpqi/smartpqi_request.c index d3c4fb989a99..c5f8ac3c41ba 100644 --- a/sys/dev/smartpqi/smartpqi_request.c +++ b/sys/dev/smartpqi/smartpqi_request.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -85,8 +85,8 @@ pqisrc_contiguous_free_elem(uint32_t pi, uint32_t ci, uint32_t elem_in_q) /* Subroutine to find out num of elements need for the request */ static uint32_t -pqisrc_num_elem_needed(pqisrc_softstate_t *softs, uint32_t SG_Count, - pqi_scsi_dev_t *devp, boolean_t is_write, IO_PATH_T io_path) +pqisrc_num_elem_needed(pqisrc_softstate_t const *softs, uint32_t SG_Count, + pqi_scsi_dev_t const *devp, boolean_t is_write, IO_PATH_T io_path) { uint32_t num_sg; uint32_t num_elem_required = 1; @@ -129,7 +129,7 @@ pqisrc_build_sgl(sgt_t *sg_array, rcb_t *rcb, iu_header_t *iu_hdr, DBG_FUNC("IN\n"); - /* DBG_IO("SGL_Count :%d",num_sg); */ + /* DBG_IO("SGL_Count :%d\n",num_sg); */ if (0 == num_sg) { goto out; } @@ -404,11 +404,11 @@ pqisrc_build_aio_common(pqisrc_softstate_t *softs, pqi_aio_req_t *aio_req, } /*Subroutine used to show standard AIO IU fields */ void -pqisrc_show_aio_common(pqisrc_softstate_t *softs, rcb_t *rcb, +pqisrc_show_aio_common(pqisrc_softstate_t *softs, rcb_t const *rcb, pqi_aio_req_t *aio_req) { #ifdef DEBUG_AIO - DBG_INFO("AIO IU Content, tag# 0x%08x", rcb->tag); + DBG_INFO("AIO IU Content, tag# 0x%08x\n", rcb->tag); DBG_INFO("%15s: 0x%x\n", "iu_type", aio_req->header.iu_type); DBG_INFO("%15s: 0x%x\n", "comp_feat", aio_req->header.comp_feature); DBG_INFO("%15s: 0x%x\n", "length", aio_req->header.iu_length); @@ -453,11 +453,11 @@ pqisrc_build_aio_R1_write(pqisrc_softstate_t *softs, { DBG_FUNC("IN\n"); if (!rcb->dvp) { - DBG_WARN("%s: DEBUG: dev ptr is null", __func__); + DBG_WARN("%s: DEBUG: dev ptr is NULL\n", __func__); return; } if (!rcb->dvp->raid_map) { - DBG_WARN("%s: DEBUG: raid_map is null", __func__); + DBG_WARN("%s: DEBUG: raid_map is NULL\n", __func__); return; } @@ -522,12 +522,12 @@ pqisrc_build_aio_R1_write(pqisrc_softstate_t *softs, /*Subroutine used to show AIO RAID1 Write bypass IU fields */ void -pqisrc_show_aio_R1_write(pqisrc_softstate_t *softs, rcb_t *rcb, +pqisrc_show_aio_R1_write(pqisrc_softstate_t *softs, rcb_t const *rcb, pqi_aio_raid1_write_req_t *aio_req) { #ifdef DEBUG_AIO - DBG_INFO("AIO RAID1 Write IU Content, tag# 0x%08x", rcb->tag); + DBG_INFO("AIO RAID1 Write IU Content, tag# 0x%08x\n", rcb->tag); DBG_INFO("%15s: 0x%x\n", "iu_type", aio_req->header.iu_type); DBG_INFO("%15s: 0x%x\n", "comp_feat", aio_req->header.comp_feature); DBG_INFO("%15s: 0x%x\n", "length", aio_req->header.iu_length); @@ -674,7 +674,7 @@ pqisrc_build_aio_R5or6_write(pqisrc_softstate_t *softs, /*Subroutine used to show AIO RAID5/6 Write bypass IU fields */ void -pqisrc_show_aio_R5or6_write(pqisrc_softstate_t *softs, rcb_t *rcb, +pqisrc_show_aio_R5or6_write(pqisrc_softstate_t *softs, rcb_t const *rcb, pqi_aio_raid5or6_write_req_t *aio_req) { #ifdef DEBUG_AIO @@ -724,7 +724,7 @@ pqisrc_show_aio_R5or6_write(pqisrc_softstate_t *softs, rcb_t *rcb, /* Is the cdb a read command? */ boolean_t -pqisrc_cdb_is_read(uint8_t *cdb) +pqisrc_cdb_is_read(uint8_t const *cdb) { if (cdb[0] == SCMD_READ_6 || cdb[0] == SCMD_READ_10 || cdb[0] == SCMD_READ_12 || cdb[0] == SCMD_READ_16) @@ -734,7 +734,7 @@ pqisrc_cdb_is_read(uint8_t *cdb) /* Is the cdb a write command? */ boolean_t -pqisrc_cdb_is_write(uint8_t *cdb) +pqisrc_cdb_is_write(uint8_t const *cdb) { if (cdb == NULL) return false; @@ -1021,7 +1021,7 @@ pqisrc_build_send_io(pqisrc_softstate_t *softs,rcb_t *rcb) /* coverity[unchecked_value] */ num_elem_needed = pqisrc_num_elem_needed(softs, OS_GET_IO_SG_COUNT(rcb), devp, is_write, io_path); - DBG_IO("num_elem_needed :%u",num_elem_needed); + DBG_IO("num_elem_needed :%u\n",num_elem_needed); do { uint32_t num_elem_available; @@ -1047,7 +1047,7 @@ pqisrc_build_send_io(pqisrc_softstate_t *softs,rcb_t *rcb) } }while(TraverseCount < 2); - DBG_IO("num_elem_alloted :%u",num_elem_alloted); + DBG_IO("num_elem_alloted :%u\n",num_elem_alloted); if (num_elem_alloted == 0) { DBG_WARN("OUT: IB Queues were full\n"); return PQI_STATUS_QFULL; @@ -1131,7 +1131,7 @@ fill_lba_for_scsi_rw(pqisrc_softstate_t *softs, uint8_t *cdb, aio_req_locator_t { if (!l) { - DBG_INFO("No locator ptr: AIO ineligible"); + DBG_INFO("No locator ptr: AIO ineligible\n"); return PQI_STATUS_FAILURE; } @@ -1172,7 +1172,7 @@ fill_lba_for_scsi_rw(pqisrc_softstate_t *softs, uint8_t *cdb, aio_req_locator_t break; default: /* Process via normal I/O path. */ - DBG_AIO("NOT read or write 6/10/12/16: AIO ineligible"); + DBG_AIO("NOT read or write 6/10/12/16: AIO ineligible\n"); return PQI_STATUS_FAILURE; } return PQI_STATUS_SUCCESS; @@ -1181,8 +1181,8 @@ fill_lba_for_scsi_rw(pqisrc_softstate_t *softs, uint8_t *cdb, aio_req_locator_t /* determine whether writes to certain types of RAID are supported. */ static boolean_t -pqisrc_is_supported_write(pqisrc_softstate_t *softs, - pqi_scsi_dev_t *device) +pqisrc_is_supported_write(pqisrc_softstate_t const *softs, + pqi_scsi_dev_t const *device) { DBG_FUNC("IN\n"); @@ -1381,7 +1381,7 @@ pqisrc_is_r5or6_single_group(pqisrc_softstate_t *softs, aio_req_locator_t *l) l->r5or6.row.blks_per_row; if (l->group.first != l->group.last) { - DBG_AIO("AIO ineligible"); + DBG_AIO("AIO ineligible\n"); ret = false; } @@ -1403,7 +1403,7 @@ pqisrc_is_r5or6_single_row(pqisrc_softstate_t *softs, aio_req_locator_t *l) l->r5or6.row.last = l->block.last / l->stripesz; if (l->r5or6.row.first != l->r5or6.row.last) { - DBG_AIO("AIO ineligible"); + DBG_AIO("AIO ineligible\n"); ret = false; } @@ -1431,7 +1431,7 @@ pqisrc_is_r5or6_single_column(pqisrc_softstate_t *softs, aio_req_locator_t *l) l->r5or6.col.last = l->r5or6.row.offset_last / l->strip_sz; if (l->r5or6.col.first != l->r5or6.col.last) { - DBG_AIO("AIO ineligible"); + DBG_AIO("AIO ineligible\n"); ret = false; } @@ -1494,7 +1494,7 @@ pqisrc_handle_blk_size_diffs(aio_req_locator_t *l) */ static boolean_t pqisrc_aio_req_too_big(pqisrc_softstate_t *softs, - pqi_scsi_dev_t *device, rcb_t *rcb, + pqi_scsi_dev_t *device, rcb_t const *rcb, aio_req_locator_t *l, uint32_t disk_blk_cnt) { boolean_t ret = false; @@ -1537,7 +1537,7 @@ pqisrc_aio_req_too_big(pqisrc_softstate_t *softs, if (size > dev_max) { - DBG_AIO("AIO ineligible: size=%u, max=%u", size, dev_max); + DBG_AIO("AIO ineligible: size=%u, max=%u\n", size, dev_max); ret = true; } @@ -1547,7 +1547,7 @@ pqisrc_aio_req_too_big(pqisrc_softstate_t *softs, #ifdef DEBUG_RAID_MAP static inline void -pqisrc_aio_show_raid_map(pqisrc_softstate_t *softs, struct raid_map *m) +pqisrc_aio_show_raid_map(pqisrc_softstate_t const *softs, struct raid_map const *m) { int i; @@ -1583,7 +1583,7 @@ pqisrc_aio_show_raid_map(pqisrc_softstate_t *softs, struct raid_map *m) static inline void pqisrc_aio_show_locator_info(pqisrc_softstate_t *softs, - aio_req_locator_t *l, uint32_t disk_blk_cnt, rcb_t *rcb) + aio_req_locator_t *l, uint32_t disk_blk_cnt, rcb_t const *rcb) { #ifdef DEBUG_AIO_LOCATOR pqisrc_aio_show_raid_map(softs, l->raid_map); @@ -1665,7 +1665,7 @@ pqisrc_aio_build_cdb(aio_req_locator_t *l, /* print any arbitrary buffer of length total_len */ void -pqisrc_print_buffer(pqisrc_softstate_t *softs, char *msg, void *user_buf, +pqisrc_print_buffer(pqisrc_softstate_t *softs, char const *msg, void *user_buf, uint32_t total_len, uint32_t flags) { #define LINE_BUF_LEN 60 @@ -1713,7 +1713,7 @@ pqisrc_print_buffer(pqisrc_softstate_t *softs, char *msg, void *user_buf, /* print CDB with column header */ void -pqisrc_show_cdb(pqisrc_softstate_t *softs, char *msg, rcb_t *rcb, uint8_t *cdb) +pqisrc_show_cdb(pqisrc_softstate_t *softs, char const *msg, rcb_t const *rcb, uint8_t *cdb) { /* Print the CDB contents */ pqisrc_print_buffer(softs, msg, cdb, rcb->cmdlen, PRINT_FLAG_HDR_COLUMN); @@ -1742,7 +1742,7 @@ pqisrc_show_rcb_details(pqisrc_softstate_t *softs, rcb_t *rcb, char *msg, void * DBG_INFO("tag=0x%x dir=%u host_timeout=%ums\n", rcb->tag, rcb->data_dir, (uint32_t)rcb->host_timeout_ms); - DBG_INFO("BTL: %d:%d:%d addr=0x%x\n", devp->bus, devp->target, + DBG_INFO("B%d:T%d:L%d addr=0x%x\n", devp->bus, devp->target, devp->lun, GET_LE32(devp->scsi3addr)); if (rcb->path == AIO_PATH) @@ -1786,7 +1786,7 @@ pqisrc_build_scsi_cmd_raidbypass(pqisrc_softstate_t *softs, return PQI_STATUS_FAILURE; } if (device->raid_map == NULL) { - DBG_INFO("tag=0x%x BTL: %d:%d:%d Raid map is NULL\n", + DBG_INFO("tag=0x%x B%d:T%d:L%d Raid map is NULL\n", rcb->tag, device->bus, device->target, device->lun); return PQI_STATUS_FAILURE; } @@ -1846,15 +1846,18 @@ pqisrc_build_scsi_cmd_raidbypass(pqisrc_softstate_t *softs, } if (l->map.idx >= RAID_MAP_MAX_ENTRIES) { - DBG_INFO("AIO ineligible: index exceeds max map entries"); + DBG_INFO("AIO ineligible: index exceeds max map entries\n"); return PQI_STATUS_FAILURE; } rcb->ioaccel_handle = l->raid_map->dev_data[l->map.idx].ioaccel_handle; + /* if (!pqisrc_calc_aio_block(l)) return PQI_STATUS_FAILURE; + */ + pqisrc_calc_aio_block(l); disk_blk_cnt = pqisrc_handle_blk_size_diffs(l); @@ -1889,8 +1892,8 @@ pqisrc_build_scsi_cmd_raidbypass(pqisrc_softstate_t *softs, */ static int -pqisrc_send_aio_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t *devp, - rcb_t *rcb, rcb_t *rcb_to_manage, int tmf_type) +pqisrc_send_aio_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t const *devp, + rcb_t *rcb, rcb_t const *rcb_to_manage, int tmf_type) { int rval = PQI_STATUS_SUCCESS; pqi_aio_tmf_req_t tmf_req; @@ -1966,8 +1969,8 @@ pqisrc_send_aio_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t *devp, /* Function used to submit a Raid TMF to the adapter */ static int -pqisrc_send_raid_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t *devp, - rcb_t *rcb, rcb_t *rcb_to_manage, int tmf_type) +pqisrc_send_raid_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t const *devp, + rcb_t *rcb, rcb_t const *rcb_to_manage, int tmf_type) { int rval = PQI_STATUS_SUCCESS; pqi_raid_tmf_req_t tmf_req; @@ -1997,9 +2000,6 @@ pqisrc_send_raid_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t *devp, tmf_type == SOP_TASK_MANAGEMENT_LUN_RESET) { /* OS_TMF_TIMEOUT_SEC - 1 to accomodate driver processing */ tmf_req.timeout_in_sec = OS_TMF_TIMEOUT_SEC - 1; - /* if OS tmf timeout is 0, set minimum value for timeout */ - if (!tmf_req.timeout_in_sec) - tmf_req.timeout_in_sec = 1; } op_ib_q = &softs->op_raid_ib_q[0]; @@ -2034,8 +2034,8 @@ pqisrc_send_raid_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t *devp, return rval; } -void -dump_tmf_details(pqisrc_softstate_t *softs, rcb_t *rcb, char *msg) +static void +dump_tmf_details(rcb_t *rcb, char const *msg) { uint32_t qid = rcb->req_q ? rcb->req_q->q_id : -1; @@ -2045,7 +2045,7 @@ dump_tmf_details(pqisrc_softstate_t *softs, rcb_t *rcb, char *msg) } int -pqisrc_send_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t *devp, +pqisrc_send_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t const *devp, rcb_t *rcb, rcb_t *rcb_to_manage, int tmf_type) { int ret = PQI_STATUS_SUCCESS; @@ -2062,11 +2062,11 @@ pqisrc_send_tmf(pqisrc_softstate_t *softs, pqi_scsi_dev_t *devp, if (tmf_type == SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK) { rcb_to_manage->host_wants_to_abort_this = true; - dump_tmf_details(softs, rcb_to_manage, "rcb_to_manage"); + dump_tmf_details(rcb_to_manage, "rcb_to_manage"); } - dump_tmf_details(softs, rcb, "rcb"); + dump_tmf_details(rcb, "rcb"); if(!devp->is_physical_device) { if (tmf_type == SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK) { @@ -2167,7 +2167,7 @@ io_type_to_ascii(io_type_t io_type) /* return the io type based on cdb */ io_type_t -get_io_type_from_cdb(uint8_t *cdb) +get_io_type_from_cdb(uint8_t const *cdb) { if (cdb == NULL) return UNKNOWN_IO_TYPE; @@ -2223,9 +2223,9 @@ pqisrc_increment_io_counters(pqisrc_softstate_t *softs, rcb_t *rcb) #if 1 /* leave this enabled while we gain confidence for each io path */ if (ret_val == 1) { - char *raid_type = counter_type_to_raid_ascii(type_index); - char *path = io_path_to_ascii(rcb->path); - char *io_ascii = io_type_to_ascii(io_type); + char const *raid_type = counter_type_to_raid_ascii(type_index); + char const *path = io_path_to_ascii(rcb->path); + char const *io_ascii = io_type_to_ascii(io_type); DBG_INFO("Got first path/type hit. " "Path=%s RaidType=%s IoType=%s\n", @@ -2238,7 +2238,7 @@ pqisrc_increment_io_counters(pqisrc_softstate_t *softs, rcb_t *rcb) /* public routine to print a particular counter with header msg */ void -print_this_counter(pqisrc_softstate_t *softs, io_counters_t *pcounter, char *msg) +print_this_counter(pqisrc_softstate_t const *softs, io_counters_t const *pcounter, char const *msg) { io_counters_t counter; uint32_t percent_reads; @@ -2280,7 +2280,7 @@ print_this_counter(pqisrc_softstate_t *softs, io_counters_t *pcounter, char *msg boolean_t is_buffer_zero(void *buffer, uint32_t size) { - char *buf = buffer; + char const *buf = buffer; DWORD ii; if (buffer == NULL || size == 0) diff --git a/sys/dev/smartpqi/smartpqi_response.c b/sys/dev/smartpqi/smartpqi_response.c index 1b4f0d86095d..38695860e520 100644 --- a/sys/dev/smartpqi/smartpqi_response.c +++ b/sys/dev/smartpqi/smartpqi_response.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -121,7 +121,7 @@ pqisrc_extract_sense_data(sense_data_u_t *sense_data, uint8_t *key, uint8_t *asc if (sense_data->fixed_format.response_code == SCSI_SENSE_RESPONSE_70 || sense_data->fixed_format.response_code == SCSI_SENSE_RESPONSE_71) { - sense_data_fixed_t *fixed = &sense_data->fixed_format; + sense_data_fixed_t const *fixed = &sense_data->fixed_format; *key = fixed->sense_key; *asc = fixed->sense_code; @@ -130,7 +130,7 @@ pqisrc_extract_sense_data(sense_data_u_t *sense_data, uint8_t *key, uint8_t *asc else if (sense_data->descriptor_format.response_code == SCSI_SENSE_RESPONSE_72 || sense_data->descriptor_format.response_code == SCSI_SENSE_RESPONSE_73) { - sense_data_descriptor_t *desc = &sense_data->descriptor_format; + sense_data_descriptor_t const *desc = &sense_data->descriptor_format; *key = desc->sense_key; *asc = desc->sense_code; @@ -146,7 +146,7 @@ pqisrc_extract_sense_data(sense_data_u_t *sense_data, uint8_t *key, uint8_t *asc /* Suppress common errors unless verbose debug flag is on */ boolean_t -suppress_innocuous_error_prints(pqisrc_softstate_t *softs, rcb_t *rcb) +suppress_innocuous_error_prints(pqisrc_softstate_t const *softs, rcb_t *rcb) { uint8_t opcode = rcb->cdbp ? rcb->cdbp[0] : 0xFF; @@ -165,7 +165,7 @@ static void pqisrc_show_sense_data_simple(pqisrc_softstate_t *softs, rcb_t *rcb, sense_data_u_t *sense_data) { uint8_t opcode = rcb->cdbp ? rcb->cdbp[0] : 0xFF; - char *path = io_path_to_ascii(rcb->path); + char const *path = io_path_to_ascii(rcb->path); uint8_t key, asc, ascq; pqisrc_extract_sense_data(sense_data, &key, &asc, &ascq); @@ -393,7 +393,7 @@ pqisrc_process_task_management_response(pqisrc_softstate_t *softs, } static int -pqisrc_process_vendor_general_response(pqi_vendor_general_response_t *response) +pqisrc_process_vendor_general_response(pqi_vendor_general_response_t const *response) { int ret = PQI_STATUS_SUCCESS; @@ -448,7 +448,7 @@ pqisrc_process_response_queue(pqisrc_softstate_t *softs, int oq_id) rcb = &softs->rcb[tag]; /* Make sure we are processing a valid response. */ if ((rcb->tag != tag) || (rcb->req_pending == false)) { - DBG_ERR("No such request pending with tag : %x rcb->tag : %x", tag, rcb->tag); + DBG_ERR("No such request pending with tag : %x rcb->tag : %x\n", tag, rcb->tag); oq_ci = (oq_ci + 1) % ob_q->num_elem; break; } diff --git a/sys/dev/smartpqi/smartpqi_sis.c b/sys/dev/smartpqi/smartpqi_sis.c index 74dcb90e7d3d..82eb999ca4b8 100644 --- a/sys/dev/smartpqi/smartpqi_sis.c +++ b/sys/dev/smartpqi/smartpqi_sis.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -84,7 +84,7 @@ sis_disable_intx(pqisrc_softstate_t *softs) void sis_disable_interrupt(pqisrc_softstate_t *softs) { - DBG_FUNC("IN"); + DBG_FUNC("IN\n"); switch(softs->intr_type) { case INTR_TYPE_FIXED: @@ -100,7 +100,7 @@ sis_disable_interrupt(pqisrc_softstate_t *softs) break; } - DBG_FUNC("OUT"); + DBG_FUNC("OUT\n"); } diff --git a/sys/dev/smartpqi/smartpqi_structures.h b/sys/dev/smartpqi/smartpqi_structures.h index 4af824fa2592..0c9ad375823d 100644 --- a/sys/dev/smartpqi/smartpqi_structures.h +++ b/sys/dev/smartpqi/smartpqi_structures.h @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,6 +35,7 @@ struct bmic_host_wellness_driver_version { uint8_t driver_version_tag[2]; uint16_t driver_version_length; char driver_version[32]; + uint8_t dont_write_tag[2]; uint8_t end_tag[2]; }OS_ATTRIBUTE_PACKED; @@ -901,6 +902,8 @@ typedef struct pqi_scsi_device { int *offload_to_mirror; /* Send next I/O accelerator RAID offload request to mirror drive. */ struct raid_map *raid_map; /* I/O accelerator RAID map */ + int *temp_offload_to_mirror; /* Temporary stored offload_to_mirror which will be freed later */ + struct raid_map *temp_raid_map; /* Temporary stored RAID map which will be freed later */ int reset_in_progress; int logical_unit_number; diff --git a/sys/dev/smartpqi/smartpqi_tag.c b/sys/dev/smartpqi/smartpqi_tag.c index 214b1bd3ce7d..d9680a65f265 100644 --- a/sys/dev/smartpqi/smartpqi_tag.c +++ b/sys/dev/smartpqi/smartpqi_tag.c @@ -1,5 +1,5 @@ /*- - * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries. + * Copyright 2016-2025 Microchip Technology, Inc. and/or its subsidiaries. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/sys/dev/smbios/smbios.c b/sys/dev/smbios/smbios.c index 8f2b4a56b37b..39663e2ee155 100644 --- a/sys/dev/smbios/smbios.c +++ b/sys/dev/smbios/smbios.c @@ -310,7 +310,7 @@ static device_method_t smbios_methods[] = { DEVMETHOD(device_probe, smbios_probe), DEVMETHOD(device_attach, smbios_attach), DEVMETHOD(device_detach, smbios_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t smbios_driver = { diff --git a/sys/dev/smbus/smb.c b/sys/dev/smbus/smb.c index 514c42b88131..fa28be3a71b0 100644 --- a/sys/dev/smbus/smb.c +++ b/sys/dev/smbus/smb.c @@ -104,7 +104,7 @@ static device_method_t smb_methods[] = { /* smbus interface */ DEVMETHOD(smbus_intr, smbus_generic_intr), - { 0, 0 } + DEVMETHOD_END }; static driver_t smb_driver = { diff --git a/sys/dev/smbus/smbconf.h b/sys/dev/smbus/smbconf.h index a6c320594064..6d2d03f11def 100644 --- a/sys/dev/smbus/smbconf.h +++ b/sys/dev/smbus/smbconf.h @@ -75,7 +75,7 @@ * ivars codes */ enum smbus_ivars { - SMBUS_IVAR_ADDR, /* slave address of the device */ + SMBUS_IVAR_ADDR = BUS_IVARS_PRIVATE, /* slave address of the device */ }; int smbus_request_bus(device_t, device_t, int); diff --git a/sys/dev/smc/if_smc.c b/sys/dev/smc/if_smc.c index cc05cfd45f67..34dd1b07861b 100644 --- a/sys/dev/smc/if_smc.c +++ b/sys/dev/smc/if_smc.c @@ -480,7 +480,7 @@ static device_method_t smc_methods[] = { DEVMETHOD(miibus_readreg, smc_miibus_readreg), DEVMETHOD(miibus_writereg, smc_miibus_writereg), DEVMETHOD(miibus_statchg, smc_miibus_statchg), - { 0, 0 } + DEVMETHOD_END }; driver_t smc_driver = { diff --git a/sys/dev/smc/if_smc_acpi.c b/sys/dev/smc/if_smc_acpi.c index 3701a742d54c..b1cf5f127b88 100644 --- a/sys/dev/smc/if_smc_acpi.c +++ b/sys/dev/smc/if_smc_acpi.c @@ -63,7 +63,7 @@ smc_acpi_probe(device_t dev) static device_method_t smc_acpi_methods[] = { /* Device interface */ DEVMETHOD(device_probe, smc_acpi_probe), - { 0, 0 } + DEVMETHOD_END }; DEFINE_CLASS_1(smc, smc_acpi_driver, smc_acpi_methods, diff --git a/sys/dev/smc/if_smc_fdt.c b/sys/dev/smc/if_smc_fdt.c index 61f3e5efae8d..1931aa9d88cb 100644 --- a/sys/dev/smc/if_smc_fdt.c +++ b/sys/dev/smc/if_smc_fdt.c @@ -68,7 +68,7 @@ smc_fdt_probe(device_t dev) static device_method_t smc_fdt_methods[] = { /* Device interface */ DEVMETHOD(device_probe, smc_fdt_probe), - { 0, 0 } + DEVMETHOD_END }; DEFINE_CLASS_1(smc, smc_fdt_driver, smc_fdt_methods, diff --git a/sys/dev/sound/macio/davbus.c b/sys/dev/sound/macio/davbus.c index 9dc3676a37a0..8e9fe78317cb 100644 --- a/sys/dev/sound/macio/davbus.c +++ b/sys/dev/sound/macio/davbus.c @@ -76,7 +76,7 @@ static device_method_t pcm_davbus_methods[] = { /* Device interface. */ DEVMETHOD(device_probe, davbus_probe), DEVMETHOD(device_attach, davbus_attach), - { 0, 0 } + DEVMETHOD_END }; static driver_t pcm_davbus_driver = { diff --git a/sys/dev/sound/macio/i2s.c b/sys/dev/sound/macio/i2s.c index 647d66c27bba..2c134f8f97fe 100644 --- a/sys/dev/sound/macio/i2s.c +++ b/sys/dev/sound/macio/i2s.c @@ -109,7 +109,7 @@ static device_method_t pcm_i2s_methods[] = { /* Device interface. */ DEVMETHOD(device_probe, i2s_probe), DEVMETHOD(device_attach, i2s_attach), - { 0, 0 } + DEVMETHOD_END }; static driver_t pcm_i2s_driver = { @@ -128,7 +128,7 @@ static device_method_t aoagpio_methods[] = { /* Device interface. */ DEVMETHOD(device_probe, aoagpio_probe), DEVMETHOD(device_attach, aoagpio_attach), - { 0, 0 } + DEVMETHOD_END }; struct aoagpio_softc { diff --git a/sys/dev/sound/macio/onyx.c b/sys/dev/sound/macio/onyx.c index d13f3da92db6..f4f825a705cc 100644 --- a/sys/dev/sound/macio/onyx.c +++ b/sys/dev/sound/macio/onyx.c @@ -80,7 +80,7 @@ static device_method_t onyx_methods[] = { /* Device interface. */ DEVMETHOD(device_probe, onyx_probe), DEVMETHOD(device_attach, onyx_attach), - { 0, 0 } + DEVMETHOD_END }; static driver_t onyx_driver = { diff --git a/sys/dev/sound/macio/snapper.c b/sys/dev/sound/macio/snapper.c index 0b31bded928f..f14009f447a8 100644 --- a/sys/dev/sound/macio/snapper.c +++ b/sys/dev/sound/macio/snapper.c @@ -106,7 +106,7 @@ static device_method_t snapper_methods[] = { /* Device interface. */ DEVMETHOD(device_probe, snapper_probe), DEVMETHOD(device_attach, snapper_attach), - { 0, 0 } + DEVMETHOD_END }; static driver_t snapper_driver = { diff --git a/sys/dev/sound/macio/tumbler.c b/sys/dev/sound/macio/tumbler.c index 505fb7ba15b1..bd40ea6b4f6b 100644 --- a/sys/dev/sound/macio/tumbler.c +++ b/sys/dev/sound/macio/tumbler.c @@ -106,7 +106,7 @@ static device_method_t tumbler_methods[] = { /* Device interface. */ DEVMETHOD(device_probe, tumbler_probe), DEVMETHOD(device_attach, tumbler_attach), - { 0, 0 } + DEVMETHOD_END }; static driver_t tumbler_driver = { diff --git a/sys/dev/sound/midi/midi.c b/sys/dev/sound/midi/midi.c index c86f5fb41b14..e70f76a44ed9 100644 --- a/sys/dev/sound/midi/midi.c +++ b/sys/dev/sound/midi/midi.c @@ -236,7 +236,7 @@ midi_out(struct snd_midi *m, uint8_t *buf, int size) return (0); } - used = MIN(size, MIDIQ_LEN(m->outq)); + used = min(size, MIDIQ_LEN(m->outq)); if (used) MIDIQ_DEQ(m->outq, buf, used); if (MIDIQ_EMPTY(m->outq)) { @@ -387,13 +387,15 @@ midi_read(struct cdev *i_dev, struct uio *uio, int ioflag) * At this point, it is certain that m->inq has data */ - used = MIN(MIDIQ_LEN(m->inq), uio->uio_resid); - used = MIN(used, MIDI_RSIZE); + used = min(MIDIQ_LEN(m->inq), uio->uio_resid); + used = min(used, MIDI_RSIZE); MIDIQ_DEQ(m->inq, buf, used); + mtx_unlock(&m->lock); retval = uiomove(buf, used, uio); if (retval) - goto err1; + goto err0; + mtx_lock(&m->lock); } /* @@ -419,7 +421,7 @@ midi_write(struct cdev *i_dev, struct uio *uio, int ioflag) int used; char buf[MIDI_WSIZE]; - retval = 0; + retval = EIO; if (m == NULL) goto err0; @@ -454,12 +456,14 @@ midi_write(struct cdev *i_dev, struct uio *uio, int ioflag) * We are certain than data can be placed on the queue */ - used = MIN(MIDIQ_AVAIL(m->outq), uio->uio_resid); - used = MIN(used, MIDI_WSIZE); + used = min(MIDIQ_AVAIL(m->outq), uio->uio_resid); + used = min(used, MIDI_WSIZE); + mtx_unlock(&m->lock); retval = uiomove(buf, used, uio); if (retval) - goto err1; + goto err0; + mtx_lock(&m->lock); MIDIQ_ENQ(m->outq, buf, used); /* * Inform the bottom half that data can be written diff --git a/sys/dev/sound/midi/midiq.h b/sys/dev/sound/midi/midiq.h index 80825974283e..8ffa4a40d23d 100644 --- a/sys/dev/sound/midi/midiq.h +++ b/sys/dev/sound/midi/midiq.h @@ -56,7 +56,7 @@ struct name { \ * No protection against overflow, underflow */ #define MIDIQ_ENQ(head, buf, size) do { \ - MIDIQ_MOVE(&(head).b[(head).h], (buf), sizeof(*(head).b) * MIN((size), (head).s - (head).h)); \ + MIDIQ_MOVE(&(head).b[(head).h], (buf), sizeof(*(head).b) * min((size), (head).s - (head).h)); \ if( (head).s - (head).h < (size) ) { \ MIDIQ_MOVE((head).b, (buf) + (head).s - (head).h, sizeof(*(head).b) * ((size) - (head).s + (head).h) ); \ } \ @@ -67,7 +67,7 @@ struct name { \ #define MIDIQ_DEQ_I(head, buf, size, move, update) do { \ if(MIDIQ_FULL(head)) (head).h=(head).t; \ - if (move) MIDIQ_MOVE((buf), &(head).b[(head).t], sizeof(*(head).b) * MIN((size), (head).s - (head).t)); \ + if (move) MIDIQ_MOVE((buf), &(head).b[(head).t], sizeof(*(head).b) * min((size), (head).s - (head).t)); \ if( (head).s - (head).t < (size) ) { \ if (move) MIDIQ_MOVE((buf) + (head).s - (head).t, (head).b, sizeof(*(head).b) * ((size) - (head).s + (head).t) ); \ } \ diff --git a/sys/dev/sound/pci/als4000.c b/sys/dev/sound/pci/als4000.c index aea7cc6d3a64..c6cbd61c927c 100644 --- a/sys/dev/sound/pci/als4000.c +++ b/sys/dev/sound/pci/als4000.c @@ -925,7 +925,7 @@ static device_method_t als_methods[] = { DEVMETHOD(device_detach, als_pci_detach), DEVMETHOD(device_suspend, als_pci_suspend), DEVMETHOD(device_resume, als_pci_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t als_driver = { diff --git a/sys/dev/sound/pci/atiixp.c b/sys/dev/sound/pci/atiixp.c index 0d2228ee16cd..39ef2f375328 100644 --- a/sys/dev/sound/pci/atiixp.c +++ b/sys/dev/sound/pci/atiixp.c @@ -1402,7 +1402,7 @@ static device_method_t atiixp_methods[] = { DEVMETHOD(device_detach, atiixp_pci_detach), DEVMETHOD(device_suspend, atiixp_pci_suspend), DEVMETHOD(device_resume, atiixp_pci_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t atiixp_driver = { diff --git a/sys/dev/sound/pci/cmi.c b/sys/dev/sound/pci/cmi.c index b5465fed5a8b..4ff58cb04b8e 100644 --- a/sys/dev/sound/pci/cmi.c +++ b/sys/dev/sound/pci/cmi.c @@ -1095,7 +1095,7 @@ static device_method_t cmi_methods[] = { DEVMETHOD(device_detach, cmi_detach), DEVMETHOD(device_resume, cmi_resume), DEVMETHOD(device_suspend, cmi_suspend), - { 0, 0 } + DEVMETHOD_END }; static driver_t cmi_driver = { diff --git a/sys/dev/sound/pci/cs4281.c b/sys/dev/sound/pci/cs4281.c index 5b0b229a021b..9899e7409212 100644 --- a/sys/dev/sound/pci/cs4281.c +++ b/sys/dev/sound/pci/cs4281.c @@ -350,7 +350,7 @@ cs4281chan_setblocksize(kobj_t obj, void *data, u_int32_t blocksize) /* 2 interrupts are possible and used in buffer (half-empty,empty), * hence factor of 2. */ - ch->blksz = MIN(blocksize, sc->bufsz / 2); + ch->blksz = min(blocksize, sc->bufsz / 2); sndbuf_resize(ch->buffer, 2, ch->blksz); ch->dma_setup = 0; adcdac_prog(ch); @@ -954,7 +954,7 @@ static device_method_t cs4281_methods[] = { DEVMETHOD(device_detach, cs4281_pci_detach), DEVMETHOD(device_suspend, cs4281_pci_suspend), DEVMETHOD(device_resume, cs4281_pci_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t cs4281_driver = { diff --git a/sys/dev/sound/pci/csapcm.c b/sys/dev/sound/pci/csapcm.c index 688aee6400d8..32c0603f78a2 100644 --- a/sys/dev/sound/pci/csapcm.c +++ b/sys/dev/sound/pci/csapcm.c @@ -1024,7 +1024,7 @@ static device_method_t pcmcsa_methods[] = { DEVMETHOD(device_suspend, pcmcsa_suspend), DEVMETHOD(device_resume, pcmcsa_resume), - { 0, 0 }, + DEVMETHOD_END }; static driver_t pcmcsa_driver = { diff --git a/sys/dev/sound/pci/envy24.c b/sys/dev/sound/pci/envy24.c index 50864a9067fd..5b74c5646a1c 100644 --- a/sys/dev/sound/pci/envy24.c +++ b/sys/dev/sound/pci/envy24.c @@ -2673,7 +2673,7 @@ static device_method_t envy24_methods[] = { DEVMETHOD(device_probe, envy24_pci_probe), DEVMETHOD(device_attach, envy24_pci_attach), DEVMETHOD(device_detach, envy24_pci_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t envy24_driver = { diff --git a/sys/dev/sound/pci/envy24ht.c b/sys/dev/sound/pci/envy24ht.c index 3aca8f92f708..aacd2b33040c 100644 --- a/sys/dev/sound/pci/envy24ht.c +++ b/sys/dev/sound/pci/envy24ht.c @@ -2567,7 +2567,7 @@ static device_method_t envy24ht_methods[] = { DEVMETHOD(device_probe, envy24ht_pci_probe), DEVMETHOD(device_attach, envy24ht_pci_attach), DEVMETHOD(device_detach, envy24ht_pci_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t envy24ht_driver = { diff --git a/sys/dev/sound/pci/es137x.c b/sys/dev/sound/pci/es137x.c index 45b953efc3fc..ab8a6db74640 100644 --- a/sys/dev/sound/pci/es137x.c +++ b/sys/dev/sound/pci/es137x.c @@ -1925,7 +1925,7 @@ static device_method_t es_methods[] = { DEVMETHOD(device_probe, es_pci_probe), DEVMETHOD(device_attach, es_pci_attach), DEVMETHOD(device_detach, es_pci_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t es_driver = { diff --git a/sys/dev/sound/pci/hda/hdac.h b/sys/dev/sound/pci/hda/hdac.h index bc0ae651a3b6..27d592242578 100644 --- a/sys/dev/sound/pci/hda/hdac.h +++ b/sys/dev/sound/pci/hda/hdac.h @@ -982,7 +982,7 @@ typedef int nid_t; ****************************************************************************/ enum hdac_device_ivars { - HDA_IVAR_CODEC_ID, + HDA_IVAR_CODEC_ID = BUS_IVARS_PRIVATE, HDA_IVAR_NODE_ID, HDA_IVAR_VENDOR_ID, HDA_IVAR_DEVICE_ID, diff --git a/sys/dev/sound/pci/hdsp-pcm.c b/sys/dev/sound/pci/hdsp-pcm.c index 5a8f2ab57d6c..93ee576a3a67 100644 --- a/sys/dev/sound/pci/hdsp-pcm.c +++ b/sys/dev/sound/pci/hdsp-pcm.c @@ -1118,7 +1118,7 @@ static device_method_t hdsp_pcm_methods[] = { DEVMETHOD(device_probe, hdsp_pcm_probe), DEVMETHOD(device_attach, hdsp_pcm_attach), DEVMETHOD(device_detach, hdsp_pcm_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t hdsp_pcm_driver = { diff --git a/sys/dev/sound/pci/hdsp.c b/sys/dev/sound/pci/hdsp.c index aefbb71807b6..4fd3647edf51 100644 --- a/sys/dev/sound/pci/hdsp.c +++ b/sys/dev/sound/pci/hdsp.c @@ -1009,7 +1009,7 @@ static device_method_t hdsp_methods[] = { DEVMETHOD(device_attach, hdsp_attach), DEVMETHOD(device_detach, hdsp_detach), DEVMETHOD(bus_child_deleted, hdsp_child_deleted), - { 0, 0 } + DEVMETHOD_END }; static driver_t hdsp_driver = { diff --git a/sys/dev/sound/pci/hdspe-pcm.c b/sys/dev/sound/pci/hdspe-pcm.c index 678693960e5e..0daa8fa8bb92 100644 --- a/sys/dev/sound/pci/hdspe-pcm.c +++ b/sys/dev/sound/pci/hdspe-pcm.c @@ -474,7 +474,7 @@ buffer_mux_port(uint32_t *dma, uint32_t *pcm, uint32_t subset, uint32_t ports, channels = hdspe_channel_count(ports, pcm_width); /* Only copy as much as supported by both hardware and pcm channel. */ - slots = hdspe_port_slot_width(subset, MIN(adat_width, pcm_width)); + slots = hdspe_port_slot_width(subset, min(adat_width, pcm_width)); /* Let the compiler inline and loop unroll common cases. */ if (slots == 2) @@ -520,7 +520,7 @@ buffer_demux_port(uint32_t *dma, uint32_t *pcm, uint32_t subset, uint32_t ports, channels = hdspe_channel_count(ports, pcm_width); /* Only copy as much as supported by both hardware and pcm channel. */ - slots = hdspe_port_slot_width(subset, MIN(adat_width, pcm_width)); + slots = hdspe_port_slot_width(subset, min(adat_width, pcm_width)); /* Let the compiler inline and loop unroll common cases. */ if (slots == 2) @@ -1109,7 +1109,7 @@ static device_method_t hdspe_pcm_methods[] = { DEVMETHOD(device_probe, hdspe_pcm_probe), DEVMETHOD(device_attach, hdspe_pcm_attach), DEVMETHOD(device_detach, hdspe_pcm_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t hdspe_pcm_driver = { diff --git a/sys/dev/sound/pci/hdspe.c b/sys/dev/sound/pci/hdspe.c index f468111cb16e..d08b42df0d82 100644 --- a/sys/dev/sound/pci/hdspe.c +++ b/sys/dev/sound/pci/hdspe.c @@ -901,7 +901,7 @@ static device_method_t hdspe_methods[] = { DEVMETHOD(device_attach, hdspe_attach), DEVMETHOD(device_detach, hdspe_detach), DEVMETHOD(bus_child_deleted, hdspe_child_deleted), - { 0, 0 } + DEVMETHOD_END }; static driver_t hdspe_driver = { diff --git a/sys/dev/sound/pci/ich.c b/sys/dev/sound/pci/ich.c index 7e7fe95dac8c..1295e7eb5bc1 100644 --- a/sys/dev/sound/pci/ich.c +++ b/sys/dev/sound/pci/ich.c @@ -1226,7 +1226,7 @@ static device_method_t ich_methods[] = { DEVMETHOD(device_detach, ich_pci_detach), DEVMETHOD(device_suspend, ich_pci_suspend), DEVMETHOD(device_resume, ich_pci_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t ich_driver = { diff --git a/sys/dev/sound/pci/maestro3.c b/sys/dev/sound/pci/maestro3.c index a8a52601d1a2..d6e1d0179225 100644 --- a/sys/dev/sound/pci/maestro3.c +++ b/sys/dev/sound/pci/maestro3.c @@ -1779,7 +1779,7 @@ static device_method_t m3_methods[] = { DEVMETHOD(device_suspend, m3_pci_suspend), DEVMETHOD(device_resume, m3_pci_resume), DEVMETHOD(device_shutdown, m3_pci_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t m3_driver = { diff --git a/sys/dev/sound/pci/neomagic.c b/sys/dev/sound/pci/neomagic.c index 1fee943d9364..9268ce722c5b 100644 --- a/sys/dev/sound/pci/neomagic.c +++ b/sys/dev/sound/pci/neomagic.c @@ -808,7 +808,7 @@ static device_method_t nm_methods[] = { DEVMETHOD(device_detach, nm_pci_detach), DEVMETHOD(device_suspend, nm_pci_suspend), DEVMETHOD(device_resume, nm_pci_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t nm_driver = { diff --git a/sys/dev/sound/pci/solo.c b/sys/dev/sound/pci/solo.c index 2b61b594a8f3..87df94b914b5 100644 --- a/sys/dev/sound/pci/solo.c +++ b/sys/dev/sound/pci/solo.c @@ -1060,7 +1060,7 @@ static device_method_t ess_methods[] = { DEVMETHOD(device_detach, ess_detach), DEVMETHOD(device_resume, ess_resume), DEVMETHOD(device_suspend, ess_suspend), - { 0, 0 } + DEVMETHOD_END }; static driver_t ess_driver = { diff --git a/sys/dev/sound/pci/t4dwave.c b/sys/dev/sound/pci/t4dwave.c index 1b659118b840..53388353d15a 100644 --- a/sys/dev/sound/pci/t4dwave.c +++ b/sys/dev/sound/pci/t4dwave.c @@ -1024,7 +1024,7 @@ static device_method_t tr_methods[] = { DEVMETHOD(device_detach, tr_pci_detach), DEVMETHOD(device_suspend, tr_pci_suspend), DEVMETHOD(device_resume, tr_pci_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t tr_driver = { diff --git a/sys/dev/sound/pci/vibes.c b/sys/dev/sound/pci/vibes.c index 1b7353464503..648370c6c973 100644 --- a/sys/dev/sound/pci/vibes.c +++ b/sys/dev/sound/pci/vibes.c @@ -923,12 +923,12 @@ sv_detach(device_t dev) { } static device_method_t sc_methods[] = { - DEVMETHOD(device_probe, sv_probe), - DEVMETHOD(device_attach, sv_attach), - DEVMETHOD(device_detach, sv_detach), - DEVMETHOD(device_resume, sv_resume), - DEVMETHOD(device_suspend, sv_suspend), - { 0, 0 } + DEVMETHOD(device_probe, sv_probe), + DEVMETHOD(device_attach, sv_attach), + DEVMETHOD(device_detach, sv_detach), + DEVMETHOD(device_resume, sv_resume), + DEVMETHOD(device_suspend, sv_suspend), + DEVMETHOD_END }; static driver_t sonicvibes_driver = { diff --git a/sys/dev/sound/pcm/ac97.c b/sys/dev/sound/pcm/ac97.c index 14ff2f6a62ab..1407d202a0d1 100644 --- a/sys/dev/sound/pcm/ac97.c +++ b/sys/dev/sound/pcm/ac97.c @@ -125,12 +125,7 @@ static const struct ac97_vendorid ac97vendorid[] = { { 0x57454300, "Winbond" }, { 0x574d4c00, "Wolfson" }, { 0x594d4800, "Yamaha" }, - /* - * XXX This is a fluke, really! The real vendor - * should be SigmaTel, not this! This should be - * removed someday! - */ - { 0x01408300, "Creative" }, + { 0x01408300, "SigmaTel" }, { 0x00000000, NULL } }; @@ -238,12 +233,7 @@ static struct ac97_codecid ac97codecid[] = { { 0x594d4800, 0x00, 0, "YMF743", 0 }, { 0x594d4802, 0x00, 0, "YMF752", 0 }, { 0x594d4803, 0x00, 0, "YMF753", 0 }, - /* - * XXX This is a fluke, really! The real codec - * should be STAC9704, not this! This should be - * removed someday! - */ - { 0x01408384, 0x00, 0, "EV1938", 0 }, + { 0x01408384, 0x00, 0, "STAC9704", 0 }, { 0, 0, 0, NULL, 0 } }; @@ -845,8 +835,7 @@ void ac97_destroy(struct ac97_info *codec) { mtx_lock(&codec->lock); - if (codec->methods != NULL) - kobj_delete(codec->methods, M_AC97); + kobj_delete(codec->methods, M_AC97); mtx_destroy(&codec->lock); free(codec, M_AC97); } @@ -1104,10 +1093,6 @@ ac97mix_uninit(struct snd_mixer *m) if (codec == NULL) return -1; - /* - if (ac97_uninitmixer(codec)) - return -1; - */ ac97_destroy(codec); return 0; } diff --git a/sys/dev/sound/pcm/buffer.c b/sys/dev/sound/pcm/buffer.c index 1db9e5661dc8..0c574ae2908c 100644 --- a/sys/dev/sound/pcm/buffer.c +++ b/sys/dev/sound/pcm/buffer.c @@ -506,29 +506,11 @@ sndbuf_dispose(struct snd_dbuf *b, u_int8_t *to, unsigned int count) return 0; } -#ifdef SND_DIAGNOSTIC -static uint32_t snd_feeder_maxfeed = 0; -SYSCTL_UINT(_hw_snd, OID_AUTO, feeder_maxfeed, CTLFLAG_RD, - &snd_feeder_maxfeed, 0, "maximum feeder count request"); - -static uint32_t snd_feeder_maxcycle = 0; -SYSCTL_UINT(_hw_snd, OID_AUTO, feeder_maxcycle, CTLFLAG_RD, - &snd_feeder_maxcycle, 0, "maximum feeder cycle"); -#endif - /* count is number of bytes we want added to destination buffer */ int sndbuf_feed(struct snd_dbuf *from, struct snd_dbuf *to, struct pcm_channel *channel, struct pcm_feeder *feeder, unsigned int count) { unsigned int cnt, maxfeed; -#ifdef SND_DIAGNOSTIC - unsigned int cycle; - - if (count > snd_feeder_maxfeed) - snd_feeder_maxfeed = count; - - cycle = 0; -#endif KASSERT(count > 0, ("can't feed 0 bytes")); @@ -544,16 +526,8 @@ sndbuf_feed(struct snd_dbuf *from, struct snd_dbuf *to, struct pcm_channel *chan break; sndbuf_acquire(to, to->tmpbuf, cnt); count -= cnt; -#ifdef SND_DIAGNOSTIC - cycle++; -#endif } while (count != 0); -#ifdef SND_DIAGNOSTIC - if (cycle > snd_feeder_maxcycle) - snd_feeder_maxcycle = cycle; -#endif - return (0); } diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c index 011dc1427c2e..c1e0d8d3bc52 100644 --- a/sys/dev/sound/pcm/channel.c +++ b/sys/dev/sound/pcm/channel.c @@ -143,7 +143,7 @@ chn_vpc_proc(int reset, int db) PCM_ACQUIRE(d); CHN_FOREACH(c, d, channels.pcm) { CHN_LOCK(c); - CHN_SETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_VOL_0DB, db); + chn_setvolume_matrix(c, SND_VOL_C_PCM, SND_CHN_T_VOL_0DB, db); if (reset != 0) chn_vpc_reset(c, SND_VOL_C_PCM, 1); CHN_UNLOCK(c); @@ -1059,7 +1059,7 @@ snd_afmt2str(uint32_t afmt, char *buf, size_t len) int chn_reset(struct pcm_channel *c, uint32_t fmt, uint32_t spd) { - int r; + int err; CHN_LOCKASSERT(c); c->feedcount = 0; @@ -1071,23 +1071,26 @@ chn_reset(struct pcm_channel *c, uint32_t fmt, uint32_t spd) c->flags |= (pcm_getflags(c->dev) & SD_F_BITPERFECT) ? CHN_F_BITPERFECT : 0; - r = CHANNEL_RESET(c->methods, c->devinfo); - if (r == 0 && fmt != 0 && spd != 0) { - r = chn_setparam(c, fmt, spd); + if ((err = CHANNEL_RESET(c->methods, c->devinfo))) + return (err); + + if (fmt != 0 && spd != 0) { + if ((err = chn_setparam(c, fmt, spd))) + return (err); fmt = 0; spd = 0; } - if (r == 0 && fmt != 0) - r = chn_setformat(c, fmt); - if (r == 0 && spd != 0) - r = chn_setspeed(c, spd); - if (r == 0) - r = chn_setlatency(c, chn_latency); - if (r == 0) { - chn_resetbuf(c); - r = CHANNEL_RESETDONE(c->methods, c->devinfo); - } - return r; + if (fmt != 0 && (err = chn_setformat(c, fmt))) + return (err); + if (spd != 0 && (err = chn_setspeed(c, spd))) + return (err); + + if ((err = chn_setlatency(c, chn_latency))) + return (err); + + chn_resetbuf(c); + + return (CHANNEL_RESETDONE(c->methods, c->devinfo)); } static struct unrhdr * @@ -1144,7 +1147,6 @@ chn_init(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, int dir, void *devinfo) { struct pcm_channel *c; - struct feeder_class *fc; struct snd_dbuf *b, *bs; char buf[CHN_NAMELEN]; int err, i, direction, *vchanrate, *vchanformat; @@ -1217,17 +1219,6 @@ chn_init(struct snddev_info *d, struct pcm_channel *parent, kobj_class_t cls, chn_vpc_reset(c, SND_VOL_C_PCM, 1); CHN_UNLOCK(c); - fc = feeder_getclass(FEEDER_ROOT); - if (fc == NULL) { - device_printf(d->dev, "%s(): failed to get feeder class\n", - __func__); - goto fail; - } - if (feeder_add(c, fc, NULL)) { - device_printf(d->dev, "%s(): failed to add feeder\n", __func__); - goto fail; - } - b = sndbuf_create(c, "primary"); bs = sndbuf_create(c, "secondary"); if (b == NULL || bs == NULL) { @@ -1647,7 +1638,7 @@ chn_vpc_reset(struct pcm_channel *c, int vc, int force) return; for (i = SND_CHN_T_BEGIN; i <= SND_CHN_T_END; i += SND_CHN_T_STEP) - CHN_SETVOLUME(c, vc, i, c->volume[vc][SND_CHN_T_VOL_0DB]); + chn_setvolume_matrix(c, vc, i, c->volume[vc][SND_CHN_T_VOL_0DB]); } static u_int32_t @@ -1760,19 +1751,6 @@ round_blksz(u_int32_t v, int round) * aggressively through possibly real time programming technique. * */ -#define CHN_LATENCY_PBLKCNT_REF \ - {{1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1}, \ - {1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1}} -#define CHN_LATENCY_PBUFSZ_REF \ - {{7, 9, 12, 13, 14, 15, 15, 15, 15, 15, 16}, \ - {11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 17}} - -#define CHN_LATENCY_RBLKCNT_REF \ - {{9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1}, \ - {9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1}} -#define CHN_LATENCY_RBUFSZ_REF \ - {{14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16}, \ - {15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17}} #define CHN_LATENCY_DATA_REF 192000 /* 48khz stereo 16bit ~ 48000 x 2 x 2 */ @@ -1780,14 +1758,22 @@ static int chn_calclatency(int dir, int latency, int bps, u_int32_t datarate, u_int32_t max, int *rblksz, int *rblkcnt) { - static int pblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = - CHN_LATENCY_PBLKCNT_REF; - static int pbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = - CHN_LATENCY_PBUFSZ_REF; - static int rblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = - CHN_LATENCY_RBLKCNT_REF; - static int rbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = - CHN_LATENCY_RBUFSZ_REF; + static int pblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = { + {1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1}, + {1, 2, 3, 4, 5, 5, 4, 3, 2, 1, 1} + }; + static int pbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = { + {7, 9, 12, 13, 14, 15, 15, 15, 15, 15, 16}, + {11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 17} + }; + static int rblkcnts[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = { + {9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1}, + {9, 8, 7, 6, 5, 5, 4, 3, 2, 1, 1} + }; + static int rbufszs[CHN_LATENCY_PROFILE_MAX + 1][CHN_LATENCY_MAX + 1] = { + {14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 16}, + {15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17} + }; u_int32_t bufsz; int lprofile, blksz, blkcnt; @@ -2092,9 +2078,23 @@ chn_setspeed(struct pcm_channel *c, uint32_t speed) int chn_setformat(struct pcm_channel *c, uint32_t format) { - uint32_t oldformat, oldspeed; + uint32_t oldformat, oldspeed, x; int ret; + /* + * Detect unsupported formats. This checks if the format is supported + * in the first place, and that no more than 1 format is specified at + * the same time. + */ + x = format & AFMT_CONVERTIBLE; + if ((x & (x - 1)) != 0) { + if (snd_verbose > 3) { + device_printf(c->dev, "%s(): Unsupported format: " + "0x%08x\n", __func__, format); + } + return (EINVAL); + } + /* XXX force stereo */ if ((format & AFMT_PASSTHROUGH) && AFMT_CHANNEL(format) < 2) { format = SND_FORMAT(format, AFMT_PASSTHROUGH_CHANNEL, @@ -2347,33 +2347,9 @@ chn_notify(struct pcm_channel *c, u_int32_t flags) * If the hwchan is running, we can't change its rate, format or * blocksize */ - run = (CHN_STARTED(c)) ? 1 : 0; + run = CHN_STARTED(c); if (run) - flags &= CHN_N_VOLUME | CHN_N_TRIGGER; - - if (flags & CHN_N_RATE) { - /* - * XXX I'll make good use of this someday. - * However this is currently being superseded by - * the availability of CHN_F_VCHAN_DYNAMIC. - */ - } - - if (flags & CHN_N_FORMAT) { - /* - * XXX I'll make good use of this someday. - * However this is currently being superseded by - * the availability of CHN_F_VCHAN_DYNAMIC. - */ - } - - if (flags & CHN_N_VOLUME) { - /* - * XXX I'll make good use of this someday, though - * soft volume control is currently pretty much - * integrated. - */ - } + flags &= CHN_N_TRIGGER; if (flags & CHN_N_BLOCKSIZE) { /* @@ -2382,16 +2358,17 @@ chn_notify(struct pcm_channel *c, u_int32_t flags) chn_setlatency(c, chn_latency); } - if ((flags & CHN_N_TRIGGER) && !(c->flags & CHN_F_VCHAN_DYNAMIC)) { - nrun = CHN_EMPTY(c, children.busy) ? 0 : 1; - if (nrun && !run) - err = chn_start(c, 1); - if (!nrun && run) - chn_abort(c); - flags &= ~CHN_N_TRIGGER; - } - if (flags & CHN_N_TRIGGER) { + if (!(c->flags & CHN_F_VCHAN_DYNAMIC)) { + nrun = !CHN_EMPTY(c, children.busy); + if (nrun && !run) + err = chn_start(c, 1); + if (!nrun && run) + chn_abort(c); + + return (err); + } + if (c->direction == PCMDIR_PLAY) { vchanformat = &c->parentsnddev->pvchanformat; vchanrate = &c->parentsnddev->pvchanrate; @@ -2400,7 +2377,6 @@ chn_notify(struct pcm_channel *c, u_int32_t flags) vchanrate = &c->parentsnddev->rvchanrate; } - /* Dynamic Virtual Channel */ if (!(c->flags & CHN_F_VCHAN_ADAPTIVE)) { bestformat = *vchanformat; bestspeed = *vchanrate; @@ -2416,6 +2392,7 @@ chn_notify(struct pcm_channel *c, u_int32_t flags) vpflags = 0; CHN_FOREACH(ch, c, children.busy) { + nrun++; CHN_LOCK(ch); if ((ch->format & AFMT_PASSTHROUGH) && snd_fmtvalid(ch->format, caps->fmtlist)) { @@ -2423,7 +2400,6 @@ chn_notify(struct pcm_channel *c, u_int32_t flags) bestspeed = ch->speed; CHN_UNLOCK(ch); vpflags = CHN_F_PASSTHROUGH; - nrun++; break; } if ((ch->flags & CHN_F_EXCLUSIVE) && vpflags == 0) { @@ -2438,13 +2414,11 @@ chn_notify(struct pcm_channel *c, u_int32_t flags) } CHN_UNLOCK(ch); vpflags = CHN_F_EXCLUSIVE; - nrun++; continue; } if (!(c->flags & CHN_F_VCHAN_ADAPTIVE) || vpflags != 0) { CHN_UNLOCK(ch); - nrun++; continue; } if (ch->speed > bestspeed) { @@ -2455,7 +2429,6 @@ chn_notify(struct pcm_channel *c, u_int32_t flags) besthwformat = snd_fmtbest(ch->format, caps->fmtlist); if (!(besthwformat & AFMT_VCHAN)) { CHN_UNLOCK(ch); - nrun++; continue; } if (AFMT_CHANNEL(besthwformat) > @@ -2466,7 +2439,6 @@ chn_notify(struct pcm_channel *c, u_int32_t flags) AFMT_BIT(besthwformat) > AFMT_BIT(bestformat)) bestformat = besthwformat; CHN_UNLOCK(ch); - nrun++; } if (bestformat == 0) @@ -2486,17 +2458,16 @@ chn_notify(struct pcm_channel *c, u_int32_t flags) c->devinfo, bestspeed); err = chn_reset(c, bestformat, bestspeed); } - if (err == 0 && dirty) { - CHN_FOREACH(ch, c, children.busy) { - CHN_LOCK(ch); - if (VCHAN_SYNC_REQUIRED(ch)) - vchan_sync(ch); - CHN_UNLOCK(ch); - } - } if (err == 0) { - if (dirty) + if (dirty) { + CHN_FOREACH(ch, c, children.busy) { + CHN_LOCK(ch); + if (VCHAN_SYNC_REQUIRED(ch)) + vchan_sync(ch); + CHN_UNLOCK(ch); + } c->flags |= CHN_F_DIRTY; + } err = chn_start(c, 1); } } @@ -2513,8 +2484,6 @@ chn_notify(struct pcm_channel *c, u_int32_t flags) vchan_sync(ch); CHN_UNLOCK(ch); } - } - if (err == 0) { c->flags |= CHN_F_DIRTY; err = chn_start(c, 1); } diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h index 6415f5c88984..6fa4338dce4a 100644 --- a/sys/dev/sound/pcm/channel.h +++ b/sys/dev/sound/pcm/channel.h @@ -255,7 +255,6 @@ struct pcm_channel { #include "channel_if.h" -int chn_reinit(struct pcm_channel *c); int chn_write(struct pcm_channel *c, struct uio *buf); int chn_read(struct pcm_channel *c, struct uio *buf); u_int32_t chn_start(struct pcm_channel *c, int force); @@ -306,15 +305,6 @@ int chn_notify(struct pcm_channel *c, u_int32_t flags); int chn_getrates(struct pcm_channel *c, int **rates); int chn_syncdestroy(struct pcm_channel *c); -#define CHN_SETVOLUME(...) chn_setvolume_matrix(__VA_ARGS__) -#if defined(SND_DIAGNOSTIC) || defined(INVARIANTS) -#define CHN_GETVOLUME(...) chn_getvolume_matrix(__VA_ARGS__) -#else -#define CHN_GETVOLUME(x, y, z) ((x)->volume[y][z]) -#endif - -#define CHN_GETMUTE(x, y, z) ((x)->muted[y][z]) - #ifdef OSSV4_EXPERIMENT int chn_getpeaks(struct pcm_channel *c, int *lpeak, int *rpeak); #endif @@ -415,11 +405,8 @@ enum { -#define CHN_N_RATE 0x00000001 -#define CHN_N_FORMAT 0x00000002 -#define CHN_N_VOLUME 0x00000004 -#define CHN_N_BLOCKSIZE 0x00000008 -#define CHN_N_TRIGGER 0x00000010 +#define CHN_N_BLOCKSIZE 0x00000001 +#define CHN_N_TRIGGER 0x00000002 #define CHN_LATENCY_MIN 0 #define CHN_LATENCY_MAX 10 diff --git a/sys/dev/sound/pcm/dsp.c b/sys/dev/sound/pcm/dsp.c index c1e836691ac7..797bfba81023 100644 --- a/sys/dev/sound/pcm/dsp.c +++ b/sys/dev/sound/pcm/dsp.c @@ -607,8 +607,9 @@ dsp_ioctl_channel(struct dsp_cdevpriv *priv, struct pcm_channel *ch, case MIXER_READ(0): switch (j) { case SOUND_MIXER_MUTE: - mute = CHN_GETMUTE(ch, SND_VOL_C_PCM, SND_CHN_T_FL) || - CHN_GETMUTE(ch, SND_VOL_C_PCM, SND_CHN_T_FR); + mute = chn_getmute_matrix(ch, + SND_VOL_C_PCM, SND_CHN_T_FL) || + chn_getmute_matrix(ch, SND_VOL_C_PCM, SND_CHN_T_FR); if (ch->direction == PCMDIR_REC) { *(int *)arg = mute << SOUND_MIXER_RECLEV; } else { @@ -618,17 +619,17 @@ dsp_ioctl_channel(struct dsp_cdevpriv *priv, struct pcm_channel *ch, case SOUND_MIXER_PCM: if (ch->direction != PCMDIR_PLAY) break; - *(int *)arg = CHN_GETVOLUME(ch, + *(int *)arg = chn_getvolume_matrix(ch, SND_VOL_C_PCM, SND_CHN_T_FL); - *(int *)arg |= CHN_GETVOLUME(ch, + *(int *)arg |= chn_getvolume_matrix(ch, SND_VOL_C_PCM, SND_CHN_T_FR) << 8; break; case SOUND_MIXER_RECLEV: if (ch->direction != PCMDIR_REC) break; - *(int *)arg = CHN_GETVOLUME(ch, + *(int *)arg = chn_getvolume_matrix(ch, SND_VOL_C_PCM, SND_CHN_T_FL); - *(int *)arg |= CHN_GETVOLUME(ch, + *(int *)arg |= chn_getvolume_matrix(ch, SND_VOL_C_PCM, SND_CHN_T_FR) << 8; break; case SOUND_MIXER_DEVMASK: diff --git a/sys/dev/sound/pcm/feeder.c b/sys/dev/sound/pcm/feeder.c index 2a7f54e5d30f..af6e367895a0 100644 --- a/sys/dev/sound/pcm/feeder.c +++ b/sys/dev/sound/pcm/feeder.c @@ -181,7 +181,7 @@ feeder_find(struct pcm_channel *c, u_int32_t type) #define score_val(s1) ((s1) & 0x3f00) #define score_cse(s1) ((s1) & 0x7f) -u_int32_t +static u_int32_t snd_fmtscore(u_int32_t fmt) { u_int32_t ret; @@ -257,13 +257,13 @@ snd_fmtbestfunc(u_int32_t fmt, u_int32_t *fmts, int cheq) return best; } -u_int32_t +static u_int32_t snd_fmtbestbit(u_int32_t fmt, u_int32_t *fmts) { return snd_fmtbestfunc(fmt, fmts, 0); } -u_int32_t +static u_int32_t snd_fmtbestchannel(u_int32_t fmt, u_int32_t *fmts) { return snd_fmtbestfunc(fmt, fmts, 1); diff --git a/sys/dev/sound/pcm/feeder.h b/sys/dev/sound/pcm/feeder.h index 1f106787ee83..e1e91d468455 100644 --- a/sys/dev/sound/pcm/feeder.h +++ b/sys/dev/sound/pcm/feeder.h @@ -63,9 +63,6 @@ struct pcm_feeder { void feeder_register(void *p); struct feeder_class *feeder_getclass(u_int32_t type); -u_int32_t snd_fmtscore(u_int32_t fmt); -u_int32_t snd_fmtbestbit(u_int32_t fmt, u_int32_t *fmts); -u_int32_t snd_fmtbestchannel(u_int32_t fmt, u_int32_t *fmts); u_int32_t snd_fmtbest(u_int32_t fmt, u_int32_t *fmts); int feeder_add(struct pcm_channel *c, struct feeder_class *fc, @@ -163,21 +160,3 @@ int feeder_matrix_oss_get_channel_order(struct pcmchan_matrix *, unsigned long long *); int feeder_matrix_oss_set_channel_order(struct pcmchan_matrix *, unsigned long long *); - -/* - * By default, various feeders only deal with sign 16/32 bit native-endian - * since it should provide the fastest processing path. Processing 8bit samples - * is too noisy due to limited dynamic range, while 24bit is quite slow due to - * unnatural per-byte read/write. However, for debugging purposes, ensuring - * implementation correctness and torture test, the following can be defined: - * - * SND_FEEDER_MULTIFORMAT - Compile all type of converters, but force - * 8bit samples to be converted to 16bit - * native-endian for better dynamic range. - * Process 24bit samples natively. - * SND_FEEDER_FULL_MULTIFORMAT - Ditto, but process 8bit samples natively. - */ -#ifdef SND_FEEDER_FULL_MULTIFORMAT -#undef SND_FEEDER_MULTIFORMAT -#define SND_FEEDER_MULTIFORMAT 1 -#endif diff --git a/sys/dev/sound/pcm/feeder_chain.c b/sys/dev/sound/pcm/feeder_chain.c index 4ec50d810253..4fc846f77496 100644 --- a/sys/dev/sound/pcm/feeder_chain.c +++ b/sys/dev/sound/pcm/feeder_chain.c @@ -66,13 +66,7 @@ struct feeder_chain_desc { #define FEEDER_CHAIN_FULLMULTI 4 #define FEEDER_CHAIN_LAST 5 -#if defined(SND_FEEDER_FULL_MULTIFORMAT) #define FEEDER_CHAIN_DEFAULT FEEDER_CHAIN_FULLMULTI -#elif defined(SND_FEEDER_MULTIFORMAT) -#define FEEDER_CHAIN_DEFAULT FEEDER_CHAIN_MULTI -#else -#define FEEDER_CHAIN_DEFAULT FEEDER_CHAIN_LEAN -#endif /* * List of preferred formats that might be required during @@ -126,7 +120,7 @@ static uint32_t *feeder_chain_formats[FEEDER_CHAIN_LAST] = { static int feeder_chain_mode = FEEDER_CHAIN_DEFAULT; -#if defined(_KERNEL) && defined(SND_DEBUG) && defined(SND_FEEDER_FULL_MULTIFORMAT) +#if defined(_KERNEL) SYSCTL_INT(_hw_snd, OID_AUTO, feeder_chain_mode, CTLFLAG_RWTUN, &feeder_chain_mode, 0, "feeder chain mode " @@ -589,12 +583,8 @@ feeder_chain(struct pcm_channel *c) case FEEDER_CHAIN_LEAN: case FEEDER_CHAIN_16: case FEEDER_CHAIN_32: -#if defined(SND_FEEDER_MULTIFORMAT) || defined(SND_FEEDER_FULL_MULTIFORMAT) case FEEDER_CHAIN_MULTI: -#endif -#if defined(SND_FEEDER_FULL_MULTIFORMAT) case FEEDER_CHAIN_FULLMULTI: -#endif break; default: feeder_chain_mode = FEEDER_CHAIN_DEFAULT; diff --git a/sys/dev/sound/pcm/feeder_mixer.c b/sys/dev/sound/pcm/feeder_mixer.c index 8c58e1c8ef33..be78b0cffb64 100644 --- a/sys/dev/sound/pcm/feeder_mixer.c +++ b/sys/dev/sound/pcm/feeder_mixer.c @@ -43,9 +43,6 @@ #include "snd_fxdiv_gen.h" #endif -#undef SND_FEEDER_MULTIFORMAT -#define SND_FEEDER_MULTIFORMAT 1 - struct feed_mixer_info { uint32_t format; uint32_t channels; @@ -174,14 +171,6 @@ feed_mixer_rec(struct pcm_channel *c) CHN_UNLOCK(ch); continue; } -#ifdef SND_DEBUG - if ((c->flags & CHN_F_DIRTY) && VCHAN_SYNC_REQUIRED(ch)) { - if (vchan_sync(ch) != 0) { - CHN_UNLOCK(ch); - continue; - } - } -#endif bs = ch->bufsoft; if (ch->flags & CHN_F_MMAP) sndbuf_dispose(bs, NULL, sndbuf_getready(bs)); @@ -270,14 +259,6 @@ feed_mixer_feed(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b, CHN_UNLOCK(ch); continue; } -#ifdef SND_DEBUG - if ((c->flags & CHN_F_DIRTY) && VCHAN_SYNC_REQUIRED(ch)) { - if (vchan_sync(ch) != 0) { - CHN_UNLOCK(ch); - continue; - } - } -#endif if ((ch->flags & CHN_F_MMAP) && !(ch->flags & CHN_F_CLOSING)) sndbuf_acquire(ch->bufsoft, NULL, sndbuf_getfree(ch->bufsoft)); diff --git a/sys/dev/sound/pcm/feeder_rate.c b/sys/dev/sound/pcm/feeder_rate.c index aee164840c4a..173f7811f547 100644 --- a/sys/dev/sound/pcm/feeder_rate.c +++ b/sys/dev/sound/pcm/feeder_rate.c @@ -89,21 +89,6 @@ #define Z_RATE_DEFAULT 48000 -#define Z_RATE_MIN FEEDRATE_RATEMIN -#define Z_RATE_MAX FEEDRATE_RATEMAX -#define Z_ROUNDHZ FEEDRATE_ROUNDHZ -#define Z_ROUNDHZ_MIN FEEDRATE_ROUNDHZ_MIN -#define Z_ROUNDHZ_MAX FEEDRATE_ROUNDHZ_MAX - -#define Z_RATE_SRC FEEDRATE_SRC -#define Z_RATE_DST FEEDRATE_DST -#define Z_RATE_QUALITY FEEDRATE_QUALITY -#define Z_RATE_CHANNELS FEEDRATE_CHANNELS - -#define Z_PARANOID 1 - -#define Z_MULTIFORMAT 1 - #ifdef _KERNEL #undef Z_USE_ALPHADRIFT #define Z_USE_ALPHADRIFT 1 @@ -151,9 +136,9 @@ struct z_info { z_resampler_t z_resample; }; -int feeder_rate_min = Z_RATE_MIN; -int feeder_rate_max = Z_RATE_MAX; -int feeder_rate_round = Z_ROUNDHZ; +int feeder_rate_min = FEEDRATE_RATEMIN; +int feeder_rate_max = FEEDRATE_RATEMAX; +int feeder_rate_round = FEEDRATE_ROUNDHZ; int feeder_rate_quality = Z_QUALITY_DEFAULT; static int feeder_rate_polyphase_max = Z_POLYPHASE_MAX; @@ -222,10 +207,10 @@ sysctl_hw_snd_feeder_rate_round(SYSCTL_HANDLER_ARGS) if (err != 0 || req->newptr == NULL || val == feeder_rate_round) return (err); - if (val < Z_ROUNDHZ_MIN || val > Z_ROUNDHZ_MAX) + if (val < FEEDRATE_ROUNDHZ_MIN || val > FEEDRATE_ROUNDHZ_MAX) return (EINVAL); - feeder_rate_round = val - (val % Z_ROUNDHZ); + feeder_rate_round = val - (val % FEEDRATE_ROUNDHZ); return (0); } @@ -622,15 +607,10 @@ z_feed_sinc_polyphase_##SIGN##BIT##ENDIAN(struct z_info *info, uint8_t *dst) \ Z_DECLARE_SINC(SIGN, BIT, ENDIAN) \ Z_DECLARE_SINC_POLYPHASE(SIGN, BIT, ENDIAN) -#if BYTE_ORDER == LITTLE_ENDIAN || defined(SND_FEEDER_MULTIFORMAT) Z_DECLARE(S, 16, LE) Z_DECLARE(S, 32, LE) -#endif -#if BYTE_ORDER == BIG_ENDIAN || defined(SND_FEEDER_MULTIFORMAT) Z_DECLARE(S, 16, BE) Z_DECLARE(S, 32, BE) -#endif -#ifdef SND_FEEDER_MULTIFORMAT Z_DECLARE(S, 8, NE) Z_DECLARE(S, 24, LE) Z_DECLARE(S, 24, BE) @@ -643,7 +623,6 @@ Z_DECLARE(U, 24, BE) Z_DECLARE(U, 32, BE) Z_DECLARE(F, 32, LE) Z_DECLARE(F, 32, BE) -#endif enum { Z_RESAMPLER_ZOH, @@ -672,15 +651,10 @@ static const struct { uint32_t format; z_resampler_t resampler[Z_RESAMPLER_LAST]; } z_resampler_tab[] = { -#if BYTE_ORDER == LITTLE_ENDIAN || defined(SND_FEEDER_MULTIFORMAT) Z_RESAMPLER_ENTRY(S, 16, LE), Z_RESAMPLER_ENTRY(S, 32, LE), -#endif -#if BYTE_ORDER == BIG_ENDIAN || defined(SND_FEEDER_MULTIFORMAT) Z_RESAMPLER_ENTRY(S, 16, BE), Z_RESAMPLER_ENTRY(S, 32, BE), -#endif -#ifdef SND_FEEDER_MULTIFORMAT Z_RESAMPLER_ENTRY(S, 8, NE), Z_RESAMPLER_ENTRY(S, 24, LE), Z_RESAMPLER_ENTRY(S, 24, BE), @@ -693,7 +667,6 @@ static const struct { Z_RESAMPLER_ENTRY(U, 32, BE), Z_RESAMPLER_ENTRY(F, 32, LE), Z_RESAMPLER_ENTRY(F, 32, BE), -#endif }; #define Z_RESAMPLER_TAB_SIZE \ @@ -728,7 +701,6 @@ z_resampler_reset(struct z_info *info) info->quality = Z_QUALITY_MAX; } -#ifdef Z_PARANOID static int32_t z_resampler_sinc_len(struct z_info *info) { @@ -766,9 +738,6 @@ z_resampler_sinc_len(struct z_info *info) return (len); } -#else -#define z_resampler_sinc_len(i) (Z_IS_SINC(i) ? Z_SINC_LEN(i) : 1) -#endif #define Z_POLYPHASE_COEFF_SHIFT 0 @@ -1422,21 +1391,21 @@ z_resampler_set(struct pcm_feeder *f, int what, int32_t value) info = f->data; switch (what) { - case Z_RATE_SRC: + case FEEDRATE_SRC: if (value < feeder_rate_min || value > feeder_rate_max) return (E2BIG); if (value == info->rsrc) return (0); info->rsrc = value; break; - case Z_RATE_DST: + case FEEDRATE_DST: if (value < feeder_rate_min || value > feeder_rate_max) return (E2BIG); if (value == info->rdst) return (0); info->rdst = value; break; - case Z_RATE_QUALITY: + case FEEDRATE_QUALITY: if (value < Z_QUALITY_MIN || value > Z_QUALITY_MAX) return (EINVAL); if (value == info->quality) @@ -1453,7 +1422,7 @@ z_resampler_set(struct pcm_feeder *f, int what, int32_t value) return (0); info->quality = oquality; break; - case Z_RATE_CHANNELS: + case FEEDRATE_CHANNELS: if (value < SND_CHN_MIN || value > SND_CHN_MAX) return (EINVAL); if (value == info->channels) @@ -1475,13 +1444,13 @@ z_resampler_get(struct pcm_feeder *f, int what) info = f->data; switch (what) { - case Z_RATE_SRC: + case FEEDRATE_SRC: return (info->rsrc); - case Z_RATE_DST: + case FEEDRATE_DST: return (info->rdst); - case Z_RATE_QUALITY: + case FEEDRATE_QUALITY: return (info->quality); - case Z_RATE_CHANNELS: + case FEEDRATE_CHANNELS: return (info->channels); } diff --git a/sys/dev/sound/pcm/feeder_volume.c b/sys/dev/sound/pcm/feeder_volume.c index fc4ed1bbb0a5..5f40816b4065 100644 --- a/sys/dev/sound/pcm/feeder_volume.c +++ b/sys/dev/sound/pcm/feeder_volume.c @@ -74,15 +74,10 @@ feed_volume_##SIGN##BIT##ENDIAN(int *vol, int *matrix, \ } while (--count != 0); \ } -#if BYTE_ORDER == LITTLE_ENDIAN || defined(SND_FEEDER_MULTIFORMAT) FEEDVOLUME_DECLARE(S, 16, LE) FEEDVOLUME_DECLARE(S, 32, LE) -#endif -#if BYTE_ORDER == BIG_ENDIAN || defined(SND_FEEDER_MULTIFORMAT) FEEDVOLUME_DECLARE(S, 16, BE) FEEDVOLUME_DECLARE(S, 32, BE) -#endif -#ifdef SND_FEEDER_MULTIFORMAT FEEDVOLUME_DECLARE(S, 8, NE) FEEDVOLUME_DECLARE(S, 24, LE) FEEDVOLUME_DECLARE(S, 24, BE) @@ -95,7 +90,6 @@ FEEDVOLUME_DECLARE(U, 24, BE) FEEDVOLUME_DECLARE(U, 32, BE) FEEDVOLUME_DECLARE(F, 32, LE) FEEDVOLUME_DECLARE(F, 32, BE) -#endif struct feed_volume_info { uint32_t bps, channels; @@ -115,15 +109,10 @@ static const struct { uint32_t format; feed_volume_t apply; } feed_volume_info_tab[] = { -#if BYTE_ORDER == LITTLE_ENDIAN || defined(SND_FEEDER_MULTIFORMAT) FEEDVOLUME_ENTRY(S, 16, LE), FEEDVOLUME_ENTRY(S, 32, LE), -#endif -#if BYTE_ORDER == BIG_ENDIAN || defined(SND_FEEDER_MULTIFORMAT) FEEDVOLUME_ENTRY(S, 16, BE), FEEDVOLUME_ENTRY(S, 32, BE), -#endif -#ifdef SND_FEEDER_MULTIFORMAT FEEDVOLUME_ENTRY(S, 8, NE), FEEDVOLUME_ENTRY(S, 24, LE), FEEDVOLUME_ENTRY(S, 24, BE), @@ -136,7 +125,6 @@ static const struct { FEEDVOLUME_ENTRY(U, 32, BE), FEEDVOLUME_ENTRY(F, 32, LE), FEEDVOLUME_ENTRY(F, 32, BE), -#endif }; #define FEEDVOLUME_TAB_SIZE ((int32_t) \ @@ -242,11 +230,14 @@ feed_volume_feed(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b, { int temp_vol[SND_CHN_T_VOL_MAX]; struct feed_volume_info *info; + struct snd_mixer *m; + struct snddev_info *d; uint32_t j, align; int i, *matrix; uint8_t *dst; const int16_t *vol; const int8_t *muted; + bool master_muted = false; /* * Fetch filter data operation. @@ -278,8 +269,14 @@ feed_volume_feed(struct pcm_feeder *f, struct pcm_channel *c, uint8_t *b, return (FEEDER_FEED(f->source, c, b, count, source)); /* Check if any controls are muted. */ + d = (c != NULL) ? c->parentsnddev : NULL; + m = (d != NULL && d->mixer_dev != NULL) ? d->mixer_dev->si_drv1 : NULL; + + if (m != NULL) + master_muted = (mix_getmutedevs(m) & (1 << SND_VOL_C_MASTER)); + for (j = 0; j != SND_CHN_T_VOL_MAX; j++) - temp_vol[j] = muted[j] ? 0 : vol[j]; + temp_vol[j] = (muted[j] || master_muted) ? 0 : vol[j]; dst = b; align = info->bps * info->channels; diff --git a/sys/dev/sound/pcm/matrix.h b/sys/dev/sound/pcm/matrix.h index e2798c651536..ffac162f41a1 100644 --- a/sys/dev/sound/pcm/matrix.h +++ b/sys/dev/sound/pcm/matrix.h @@ -29,11 +29,6 @@ #ifndef _SND_MATRIX_H_ #define _SND_MATRIX_H_ -#undef SND_MULTICHANNEL -#ifndef SND_OLDSTEREO -#define SND_MULTICHANNEL 1 -#endif - /* * XXX = unused, but part of the definition (will be used someday, maybe). */ @@ -176,18 +171,12 @@ #define SND_CHN_T_END SND_CHN_T_TBR #define SND_CHN_T_STEP 1 #define SND_CHN_MIN 1 - -#ifdef SND_MULTICHANNEL #define SND_CHN_MAX 8 -#else -#define SND_CHN_MAX 2 -#endif /* * Multichannel interleaved volume matrix. Each calculated value relative * to master and 0db will be stored in each CLASS + 1 as long as - * chn_setvolume_matrix() or the equivalent CHN_SETVOLUME() macros is - * used (see channel.c). + * chn_setvolume_matrix() is used (see channel.c). */ #define SND_VOL_C_MASTER 0 #define SND_VOL_C_PCM 1 diff --git a/sys/dev/sound/pcm/mixer.c b/sys/dev/sound/pcm/mixer.c index 55b61ccb4911..6ed2d0c3ce5c 100644 --- a/sys/dev/sound/pcm/mixer.c +++ b/sys/dev/sound/pcm/mixer.c @@ -1142,9 +1142,9 @@ mixer_ioctl_channel_proc: center = (left + right) >> 1; chn_setvolume_multi(c, SND_VOL_C_PCM, left, right, center); } else if ((cmd & ~0xff) == MIXER_READ(0)) { - *(int *)arg = CHN_GETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_FL); + *(int *)arg = chn_getvolume_matrix(c, SND_VOL_C_PCM, SND_CHN_T_FL); *(int *)arg |= - CHN_GETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_FR) << 8; + chn_getvolume_matrix(c, SND_VOL_C_PCM, SND_CHN_T_FR) << 8; } CHN_UNLOCK(c); diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c index 8ce369bfce5e..305d663cd6ad 100644 --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c @@ -81,6 +81,7 @@ static int sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS) { struct snddev_info *d; + char buf[32]; int error, unit; unit = snd_unit; @@ -95,6 +96,12 @@ sysctl_hw_snd_default_unit(SYSCTL_HANDLER_ARGS) snd_unit = unit; snd_unit_auto = 0; 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); } @@ -476,6 +483,8 @@ pcm_unregister(device_t 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); } return (0); diff --git a/sys/dev/sound/sndstat.c b/sys/dev/sound/sndstat.c index b0ac7f7d0824..c28a932c784e 100644 --- a/sys/dev/sound/sndstat.c +++ b/sys/dev/sound/sndstat.c @@ -487,9 +487,9 @@ sndstat_build_sound4_nvlist(struct snddev_info *d, nvlist_t **dip) c->feedcount); nvlist_add_number(cdi, SNDST_DSPS_SOUND4_CHAN_XRUNS, c->xruns); nvlist_add_number(cdi, SNDST_DSPS_SOUND4_CHAN_LEFTVOL, - CHN_GETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_FL)); + chn_getvolume_matrix(c, SND_VOL_C_PCM, SND_CHN_T_FL)); nvlist_add_number(cdi, SNDST_DSPS_SOUND4_CHAN_RIGHTVOL, - CHN_GETVOLUME(c, SND_VOL_C_PCM, SND_CHN_T_FR)); + chn_getvolume_matrix(c, SND_VOL_C_PCM, SND_CHN_T_FR)); nvlist_add_number(cdi, SNDST_DSPS_SOUND4_CHAN_HWBUF_FORMAT, c->bufhard->fmt); nvlist_add_number(cdi, SNDST_DSPS_SOUND4_CHAN_HWBUF_RATE, diff --git a/sys/dev/sound/usb/uaudio.c b/sys/dev/sound/usb/uaudio.c index 0987ca12d933..65976ced8a75 100644 --- a/sys/dev/sound/usb/uaudio.c +++ b/sys/dev/sound/usb/uaudio.c @@ -150,12 +150,11 @@ SYSCTL_INT(_hw_usb_uaudio, OID_AUTO, debug, CTLFLAG_RWTUN, #define UAUDIO_NCHANBUFS 2 /* number of outstanding request */ #define UAUDIO_RECURSE_LIMIT 255 /* rounds */ #define UAUDIO_BITS_MAX 32 /* maximum sample size in bits */ -#define UAUDIO_CHANNELS_MAX MIN(64, AFMT_CHANNEL_MAX) +#define UAUDIO_CHANNELS_MAX min(64, AFMT_CHANNEL_MAX) #define UAUDIO_MATRIX_MAX 8 /* channels */ #define MAKE_WORD(h,l) (((h) << 8) | (l)) #define BIT_TEST(bm,bno) (((bm)[(bno) / 8] >> (7 - ((bno) % 8))) & 1) -#define UAUDIO_MAX_CHAN(x) (x) #define MIX(sc) ((sc)->sc_mixer_node) union uaudio_asid { @@ -368,7 +367,6 @@ struct uaudio_softc_child { }; struct uaudio_softc { - struct sndcard_func sc_sndcard_func; struct uaudio_chan sc_rec_chan[UAUDIO_MAX_CHILD]; struct uaudio_chan sc_play_chan[UAUDIO_MAX_CHILD]; struct umidi_chan sc_midi_chan; @@ -556,9 +554,9 @@ static int umidi_open(struct usb_fifo *, int); static int umidi_ioctl(struct usb_fifo *, u_long cmd, void *, int); static void umidi_close(struct usb_fifo *, int); static void umidi_init(device_t dev); -static int umidi_probe(device_t dev); +static int umidi_attach(device_t dev); static int umidi_detach(device_t dev); -static int uaudio_hid_probe(struct uaudio_softc *sc, +static int uaudio_hid_attach(struct uaudio_softc *sc, struct usb_attach_arg *uaa); static void uaudio_hid_detach(struct uaudio_softc *sc); @@ -1101,7 +1099,7 @@ uaudio_attach(device_t dev) } if (sc->sc_midi_chan.valid) { - if (umidi_probe(dev)) { + if (umidi_attach(dev)) { goto detach; } device_printf(dev, "MIDI sequencer.\n"); @@ -1113,8 +1111,6 @@ uaudio_attach(device_t dev) /* attach the children */ - sc->sc_sndcard_func.func = SCF_PCM; - /* * Only attach a PCM device if we have a playback, recording * or mixer device present: @@ -1131,14 +1127,12 @@ uaudio_attach(device_t dev) DPRINTF("out of memory\n"); goto detach; } - device_set_ivars(sc->sc_child[i].pcm_device, - &sc->sc_sndcard_func); } bus_attach_children(dev); if (uaudio_handle_hid) { - if (uaudio_hid_probe(sc, uaa) == 0) { + if (uaudio_hid_attach(sc, uaa) == 0) { device_printf(dev, "HID volume keys found.\n"); } else { device_printf(dev, "No HID volume keys found.\n"); @@ -1651,7 +1645,7 @@ uaudio20_check_rate(struct usb_device *udev, uint8_t iface_no, * buffer. Try using a larger buffer and see if that * helps: */ - rates = MIN(UAUDIO20_MAX_RATES, (255 - 2) / 12); + rates = min(UAUDIO20_MAX_RATES, (255 - 2) / 12); error = USB_ERR_INVAL; } else { rates = UGETW(data); @@ -1993,7 +1987,7 @@ uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev, uint16_t wFormat; wFormat = UGETW(asid.v1->wFormatTag); - bChannels = UAUDIO_MAX_CHAN(asf1d.v1->bNrChannels); + bChannels = asf1d.v1->bNrChannels; bBitResolution = asf1d.v1->bSubFrameSize * 8; if (asf1d.v1->bSamFreqType == 0) { @@ -2074,8 +2068,7 @@ uaudio_chan_fill_info_sub(struct uaudio_softc *sc, struct usb_device *udev, else chan_alt->usb_cfg = uaudio_cfg_play; - chan_alt->sample_size = (UAUDIO_MAX_CHAN(channels) * - p_fmt->bPrecision) / 8; + chan_alt->sample_size = (channels * p_fmt->bPrecision) / 8; chan_alt->channels = channels; if (ep_dir == UE_DIR_IN && @@ -5805,9 +5798,7 @@ tr_setup: } } - chan->curr_cable++; - if (chan->curr_cable >= chan->max_emb_jack) - chan->curr_cable = 0; + chan->curr_cable %= chan->max_emb_jack; if (chan->curr_cable == start_cable) { if (tr_any == 0) @@ -5987,7 +5978,7 @@ static struct usb_fifo_methods umidi_fifo_methods = { }; static int -umidi_probe(device_t dev) +umidi_attach(device_t dev) { struct uaudio_softc *sc = device_get_softc(dev); struct usb_attach_arg *uaa = device_get_ivars(dev); @@ -6174,7 +6165,7 @@ tr_setup: } static int -uaudio_hid_probe(struct uaudio_softc *sc, +uaudio_hid_attach(struct uaudio_softc *sc, struct usb_attach_arg *uaa) { void *d_ptr; diff --git a/sys/dev/sound/usb/uaudio_pcm.c b/sys/dev/sound/usb/uaudio_pcm.c index 0b3da9b20440..c24c111f983c 100644 --- a/sys/dev/sound/usb/uaudio_pcm.c +++ b/sys/dev/sound/usb/uaudio_pcm.c @@ -190,18 +190,7 @@ MIXER_DECLARE(ua_mixer); static int ua_probe(device_t dev) { - struct sndcard_func *func; - - /* the parent device has already been probed */ - - func = device_get_ivars(dev); - - if ((func == NULL) || - (func->func != SCF_PCM)) { - return (ENXIO); - } - - return (BUS_PROBE_DEFAULT); + return (0); } static int diff --git a/sys/dev/speaker/spkr.c b/sys/dev/speaker/spkr.c index c698a4820434..d6ae47fdae99 100644 --- a/sys/dev/speaker/spkr.c +++ b/sys/dev/speaker/spkr.c @@ -10,6 +10,7 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/module.h> +#include <sys/sx.h> #include <sys/uio.h> #include <sys/conf.h> #include <sys/ctype.h> @@ -24,7 +25,6 @@ static d_ioctl_t spkrioctl; static struct cdevsw spkr_cdevsw = { .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, .d_open = spkropen, .d_close = spkrclose, .d_write = spkrwrite, @@ -50,11 +50,12 @@ static MALLOC_DEFINE(M_SPKR, "spkr", "Speaker buffer"); #define SPKRPRI PSOCK static char endtone, endrest; +struct spkr_state; static void tone(unsigned int thz, unsigned int centisecs); static void rest(int centisecs); -static void playinit(void); -static void playtone(int pitch, int value, int sustain); -static void playstring(char *cp, size_t slen); +static void playinit(struct spkr_state *state); +static void playtone(struct spkr_state *state, int pitch, int value, int sustain); +static void playstring(struct spkr_state *state, char *cp, size_t slen); /* * Emit tone of frequency thz for given number of centisecs @@ -71,23 +72,27 @@ tone(unsigned int thz, unsigned int centisecs) (void) printf("tone: thz=%d centisecs=%d\n", thz, centisecs); #endif /* DEBUG */ - /* set timer to generate clicks at given frequency in Hertz */ + /* + * Acquire the i8254 clock, configure it to drive the speaker + * signal, and turn on the speaker. + */ if (timer_spkr_acquire()) { - /* enter list of waiting procs ??? */ return; } - disable_intr(); + /* Configure the speaker with the tone frequency. */ timer_spkr_setfreq(thz); - enable_intr(); /* - * Set timeout to endtone function, then give up the timeslice. - * This is so other processes can execute while the tone is being + * Make the current thread sleep while the tone is being * emitted. */ timo = centisecs * hz / 100; if (timo > 0) tsleep(&endtone, SPKRPRI | PCATCH, "spkrtn", timo); + + /* + * Turn off the speaker and release the i8254 clock. + */ timer_spkr_release(); } @@ -123,12 +128,16 @@ rest(int centisecs) #define dtoi(c) ((c) - '0') -static int octave; /* currently selected octave */ -static int whole; /* whole-note time at current tempo, in ticks */ -static int value; /* whole divisor for note time, quarter note = 1 */ -static int fill; /* controls spacing of notes */ -static bool octtrack; /* octave-tracking on? */ -static bool octprefix; /* override current octave-tracking state? */ +struct spkr_state { + char *inbuf; /* incoming melody buffer */ + + int octave; /* currently selected octave */ + int whole; /* whole-note time at current tempo, in ticks */ + int value; /* whole divisor for note time, quarter note = 1 */ + int fill; /* controls spacing of notes */ + bool octtrack; /* octave-tracking on? */ + bool octprefix; /* override current octave-tracking state? */ +}; /* * Magic number avoidance... @@ -149,7 +158,7 @@ static bool octprefix; /* override current octave-tracking state? */ #define DENOM_MULT 2 /* denominator of dot multiplier */ /* letter to half-tone: A B C D E F G */ -static int notetab[8] = {9, 11, 0, 2, 4, 5, 7}; +static const int notetab[8] = {9, 11, 0, 2, 4, 5, 7}; /* * This is the American Standard A440 Equal-Tempered scale with frequencies @@ -157,7 +166,7 @@ static int notetab[8] = {9, 11, 0, 2, 4, 5, 7}; * our octave 0 is standard octave 2. */ #define OCTAVE_NOTES 12 /* semitones per octave */ -static int pitchtab[] = +static const int pitchtab[] = { /* C C# D D# E F F# G G# A A# B*/ /* 0 */ 65, 69, 73, 78, 82, 87, 93, 98, 103, 110, 117, 123, @@ -170,23 +179,25 @@ static int pitchtab[] = }; static void -playinit(void) +playinit(struct spkr_state *state) { - octave = DFLT_OCTAVE; - whole = (100 * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO; - fill = NORMAL; - value = DFLT_VALUE; - octtrack = false; - octprefix = true; /* act as though there was an initial O(n) */ + state->octave = DFLT_OCTAVE; + state->whole = (100 * SECS_PER_MIN * WHOLE_NOTE) / DFLT_TEMPO; + state->fill = NORMAL; + state->value = DFLT_VALUE; + state->octtrack = false; + state->octprefix = true; /* act as though there was an initial O(n) */ } /* * Play tone of proper duration for current rhythm signature */ static void -playtone(int pitch, int value, int sustain) +playtone(struct spkr_state *state, int pitch, int value, int sustain) { int sound, silence, snum = 1, sdenom = 1; + int whole = state->whole; + int fill = state->fill; /* this weirdness avoids floating-point arithmetic */ for (; sustain; sustain--) { @@ -220,7 +231,7 @@ playtone(int pitch, int value, int sustain) * Interpret and play an item from a notation string */ static void -playstring(char *cp, size_t slen) +playstring(struct spkr_state *state, char *cp, size_t slen) { int pitch, oldfill, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE; @@ -235,15 +246,15 @@ playstring(char *cp, size_t slen) #endif /* DEBUG */ switch (c) { - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': case 'G': /* compute pitch */ - pitch = notetab[c - 'A'] + octave * OCTAVE_NOTES; + pitch = notetab[c - 'A'] + state->octave * OCTAVE_NOTES; /* this may be followed by an accidental sign */ if (cp[1] == '#' || cp[1] == '+') { @@ -261,26 +272,26 @@ playstring(char *cp, size_t slen) * setting prefix, find the version of the current letter note * closest to the last regardless of octave. */ - if (octtrack && !octprefix) { + if (state->octtrack && !state->octprefix) { if (abs(pitch-lastpitch) > abs(pitch+OCTAVE_NOTES - lastpitch)) { - ++octave; + ++state->octave; pitch += OCTAVE_NOTES; } if (abs(pitch-lastpitch) > abs((pitch-OCTAVE_NOTES) - lastpitch)) { - --octave; + --state->octave; pitch -= OCTAVE_NOTES; } } - octprefix = false; + state->octprefix = false; lastpitch = pitch; /* ...which may in turn be followed by an override time value */ GETNUM(cp, timeval); if (timeval <= 0 || timeval > MIN_VALUE) - timeval = value; + timeval = state->value; /* ...and/or sustain dots */ for (sustain = 0; cp[1] == '.'; cp++) { @@ -289,43 +300,43 @@ playstring(char *cp, size_t slen) } /* ...and/or a slur mark */ - oldfill = fill; + oldfill = state->fill; if (cp[1] == '_') { - fill = LEGATO; + state->fill = LEGATO; ++cp; slen--; } /* time to emit the actual tone */ - playtone(pitch, timeval, sustain); + playtone(state, pitch, timeval, sustain); - fill = oldfill; + state->fill = oldfill; break; case 'O': if (cp[1] == 'N' || cp[1] == 'n') { - octprefix = octtrack = false; + state->octprefix = state->octtrack = false; ++cp; slen--; } else if (cp[1] == 'L' || cp[1] == 'l') { - octtrack = true; + state->octtrack = true; ++cp; slen--; } else { - GETNUM(cp, octave); - if (octave >= nitems(pitchtab) / OCTAVE_NOTES) - octave = DFLT_OCTAVE; - octprefix = true; + GETNUM(cp, state->octave); + if (state->octave >= nitems(pitchtab) / OCTAVE_NOTES) + state->octave = DFLT_OCTAVE; + state->octprefix = true; } break; case '>': - if (octave < nitems(pitchtab) / OCTAVE_NOTES - 1) - octave++; - octprefix = true; + if (state->octave < nitems(pitchtab) / OCTAVE_NOTES - 1) + state->octave++; + state->octprefix = true; break; case '<': - if (octave > 0) - octave--; - octprefix = true; + if (state->octave > 0) + state->octave--; + state->octprefix = true; break; case 'N': GETNUM(cp, pitch); @@ -333,49 +344,49 @@ playstring(char *cp, size_t slen) slen--; sustain++; } - oldfill = fill; + oldfill = state->fill; if (cp[1] == '_') { - fill = LEGATO; + state->fill = LEGATO; ++cp; slen--; } - playtone(pitch - 1, value, sustain); - fill = oldfill; + playtone(state, pitch - 1, state->value, sustain); + state->fill = oldfill; break; case 'L': - GETNUM(cp, value); - if (value <= 0 || value > MIN_VALUE) - value = DFLT_VALUE; + GETNUM(cp, state->value); + if (state->value <= 0 || state->value > MIN_VALUE) + state->value = DFLT_VALUE; break; case 'P': case '~': /* this may be followed by an override time value */ GETNUM(cp, timeval); if (timeval <= 0 || timeval > MIN_VALUE) - timeval = value; + timeval = state->value; for (sustain = 0; cp[1] == '.'; cp++) { slen--; sustain++; } - playtone(-1, timeval, sustain); + playtone(state, -1, timeval, sustain); break; case 'T': GETNUM(cp, tempo); if (tempo < MIN_TEMPO || tempo > MAX_TEMPO) tempo = DFLT_TEMPO; - whole = (100 * SECS_PER_MIN * WHOLE_NOTE) / tempo; + state->whole = (100 * SECS_PER_MIN * WHOLE_NOTE) / tempo; break; case 'M': if (cp[1] == 'N' || cp[1] == 'n') { - fill = NORMAL; + state->fill = NORMAL; ++cp; slen--; } else if (cp[1] == 'L' || cp[1] == 'l') { - fill = LEGATO; + state->fill = LEGATO; ++cp; slen--; } else if (cp[1] == 'S' || cp[1] == 's') { - fill = STACCATO; + state->fill = STACCATO; ++cp; slen--; } @@ -390,53 +401,82 @@ playstring(char *cp, size_t slen) * endtone(), and rest() functions defined above. */ -static bool spkr_active = false; /* exclusion flag */ -static char *spkr_inbuf; /* incoming buf */ +/* + * we use a lock to prevent interleaving of melodies written + * concurrently from two different threads. + */ +static struct sx spkr_op_locked; + +static void +spkr_dtor(void *data) +{ + struct spkr_state *state = data; + + free(state->inbuf, M_SPKR); + free(state, M_SPKR); +} static int spkropen(struct cdev *dev, int flags, int fmt, struct thread *td) { + struct spkr_state *state; + int error; #ifdef DEBUG (void) printf("spkropen: entering with dev = %s\n", devtoname(dev)); #endif /* DEBUG */ - if (spkr_active) - return(EBUSY); - else { -#ifdef DEBUG - (void) printf("spkropen: about to perform play initialization\n"); -#endif /* DEBUG */ - playinit(); - spkr_inbuf = malloc(DEV_BSIZE, M_SPKR, M_WAITOK); - spkr_active = true; - return(0); - } + /* allocate per-fd state */ + state = malloc(sizeof(*state), M_SPKR, M_WAITOK | M_ZERO); + state->inbuf = malloc(DEV_BSIZE, M_SPKR, M_WAITOK); + + /* initialize playstring state */ + playinit(state); + + /* store in the current fd private data */ + error = devfs_set_cdevpriv(state, spkr_dtor); + if (error) { + free(state->inbuf, M_SPKR); + free(state, M_SPKR); + return (error); + } + + return (0); } static int spkrwrite(struct cdev *dev, struct uio *uio, int ioflag) { + struct spkr_state *state; + int error; + unsigned n; + #ifdef DEBUG printf("spkrwrite: entering with dev = %s, count = %zd\n", devtoname(dev), uio->uio_resid); #endif /* DEBUG */ - if (uio->uio_resid > (DEV_BSIZE - 1)) /* prevent system crashes */ - return(E2BIG); - else { - unsigned n; - char *cp; - int error; + /* is the melody too long? */ + if (uio->uio_resid > (DEV_BSIZE - 1)) + return (E2BIG); - n = uio->uio_resid; - cp = spkr_inbuf; - error = uiomove(cp, n, uio); - if (!error) { - cp[n] = '\0'; - playstring(cp, n); - } - return(error); - } + /* get this fd's state */ + error = devfs_get_cdevpriv((void **)&state); + if (error) + return (error); + + /* copy melody from userspace */ + n = uio->uio_resid; + error = uiomove(state->inbuf, n, uio); + if (error) + return (error); + state->inbuf[n] = '\0'; + + /* play the melody. */ + sx_xlock(&spkr_op_locked); + playstring(state, state->inbuf, n); + sx_xunlock(&spkr_op_locked); + + return (0); } static int @@ -448,9 +488,8 @@ spkrclose(struct cdev *dev, int flags, int fmt, struct thread *td) wakeup(&endtone); wakeup(&endrest); - free(spkr_inbuf, M_SPKR); - spkr_active = false; - return(0); + /* devfs_clear_cdevpriv() calls spkr_dtor automatically */ + return (0); } static int @@ -465,20 +504,25 @@ spkrioctl(struct cdev *dev, unsigned long cmd, caddr_t cmdarg, int flags, if (cmd == SPKRTONE) { tone_t *tp = (tone_t *)cmdarg; + sx_xlock(&spkr_op_locked); if (tp->frequency == 0) rest(tp->duration); else tone(tp->frequency, tp->duration); - return 0; + sx_xunlock(&spkr_op_locked); + return (0); } else if (cmd == SPKRTUNE) { tone_t *tp = (tone_t *)(*(caddr_t *)cmdarg); tone_t ttp; int error; + sx_xlock(&spkr_op_locked); for (; ; tp++) { error = copyin(tp, &ttp, sizeof(tone_t)); - if (error) - return(error); + if (error) { + sx_xunlock(&spkr_op_locked); + return (error); + } if (ttp.duration == 0) break; @@ -488,9 +532,10 @@ spkrioctl(struct cdev *dev, unsigned long cmd, caddr_t cmdarg, int flags, else tone(ttp.frequency, ttp.duration); } - return(0); + sx_xunlock(&spkr_op_locked); + return (0); } - return(EINVAL); + return (EINVAL); } static struct cdev *speaker_dev; @@ -504,13 +549,15 @@ speaker_modevent(module_t mod, int type, void *data) int error = 0; switch(type) { - case MOD_LOAD: + case MOD_LOAD: + sx_init(&spkr_op_locked, "spkr"); speaker_dev = make_dev(&spkr_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "speaker"); break; case MOD_SHUTDOWN: case MOD_UNLOAD: destroy_dev(speaker_dev); + sx_destroy(&spkr_op_locked); break; default: error = EOPNOTSUPP; diff --git a/sys/dev/spibus/spibusvar.h b/sys/dev/spibus/spibusvar.h index 25cd380173ad..82100f767bda 100644 --- a/sys/dev/spibus/spibusvar.h +++ b/sys/dev/spibus/spibusvar.h @@ -48,7 +48,7 @@ struct spibus_ivar #define SPIBUS_CS_HIGH (1U << 31) enum { - SPIBUS_IVAR_CS, /* chip select that we're on */ + SPIBUS_IVAR_CS = BUS_IVARS_PRIVATE, /* chip select that we're on */ SPIBUS_IVAR_MODE, /* SPI mode (0-3) */ SPIBUS_IVAR_CLOCK, /* maximum clock freq for device */ SPIBUS_IVAR_CS_DELAY, /* delay in microseconds after toggling chip select */ diff --git a/sys/dev/spibus/spigen.c b/sys/dev/spibus/spigen.c index 66c93e927281..8f7dbb504537 100644 --- a/sys/dev/spibus/spigen.c +++ b/sys/dev/spibus/spigen.c @@ -73,7 +73,7 @@ struct spigen_softc { struct spigen_mmap { vm_object_t bufobj; - vm_offset_t kvaddr; + void *kvaddr; size_t bufsize; }; @@ -235,10 +235,10 @@ spigen_transfer_mmapped(struct cdev *cdev, struct spigen_transfer_mmapped *stm) if (mmap->bufsize < stm->stm_command_length + stm->stm_data_length) return (E2BIG); - transfer.tx_cmd = transfer.rx_cmd = (void *)((uintptr_t)mmap->kvaddr); + transfer.tx_cmd = transfer.rx_cmd = mmap->kvaddr; transfer.tx_cmd_sz = transfer.rx_cmd_sz = stm->stm_command_length; transfer.tx_data = transfer.rx_data = - (void *)((uintptr_t)mmap->kvaddr + stm->stm_command_length); + (void *)((char *)mmap->kvaddr + stm->stm_command_length); transfer.tx_data_sz = transfer.rx_data_sz = stm->stm_data_length; error = SPIBUS_TRANSFER(device_get_parent(dev), dev, &transfer); @@ -283,8 +283,10 @@ spigen_mmap_cleanup(void *arg) { struct spigen_mmap *mmap = arg; - if (mmap->kvaddr != 0) + if (mmap->kvaddr != NULL) { pmap_qremove(mmap->kvaddr, mmap->bufsize / PAGE_SIZE); + kva_free(mmap->kvaddr, mmap->bufsize); + } if (mmap->bufobj != NULL) vm_object_deallocate(mmap->bufobj); free(mmap, M_DEVBUF); @@ -379,7 +381,7 @@ static device_method_t spigen_methods[] = { DEVMETHOD(device_probe, spigen_probe), DEVMETHOD(device_attach, spigen_attach), DEVMETHOD(device_detach, spigen_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t spigen_driver = { diff --git a/sys/dev/superio/superio.h b/sys/dev/superio/superio.h index c19ffbb43fe2..82530b14429b 100644 --- a/sys/dev/superio/superio.h +++ b/sys/dev/superio/superio.h @@ -60,7 +60,7 @@ device_t superio_find_dev(device_t superio, superio_dev_type_t type, int ldn); enum superio_ivars { - SUPERIO_IVAR_LDN = 10600, + SUPERIO_IVAR_LDN = BUS_IVARS_SUPERIO, SUPERIO_IVAR_TYPE, SUPERIO_IVAR_IOBASE, SUPERIO_IVAR_IOBASE2, diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c index b4e5c1075fb4..1399eadb21fb 100644 --- a/sys/dev/sym/sym_hipd.c +++ b/sys/dev/sym/sym_hipd.c @@ -58,7 +58,6 @@ */ #include <sys/cdefs.h> -#define SYM_DRIVER_NAME "sym-1.6.5-20000902" /* #define SYM_DEBUG_GENERIC_SUPPORT */ @@ -114,17 +113,15 @@ typedef u_int32_t u32; #include <dev/sym/sym_fw.h> /* - * IA32 architecture does not reorder STORES and prevents - * LOADS from passing STORES. It is called `program order' - * by Intel and allows device drivers to deal with memory - * ordering by only ensuring that the code is not reordered - * by the compiler when ordering is required. - * Other architectures implement a weaker ordering that - * requires memory barriers (and also IO barriers when they - * make sense) to be used. + * With uncacheable memory, x86 does not reorder STORES and prevents LOADS + * from passing STORES. For ensuring this program order, we still need to + * employ compiler barriers, though, when the ordering of LOADS and STORES + * matters. + * Other architectures may implement weaker ordering guarantees and, thus, + * require memory barriers (and also IO barriers) to be used. */ #if defined __i386__ || defined __amd64__ -#define MEMORY_BARRIER() do { ; } while(0) +#define MEMORY_BARRIER() __compiler_membar() #elif defined __powerpc__ #define MEMORY_BARRIER() __asm__ volatile("eieio; sync" : : : "memory") #elif defined __arm__ @@ -594,10 +591,10 @@ static m_addr_t ___dma_getp(m_pool_s *mp) goto out_err; if (bus_dmamem_alloc(mp->dmat, &vaddr, - BUS_DMA_COHERENT | BUS_DMA_WAITOK, &vbp->dmamap)) + BUS_DMA_COHERENT | BUS_DMA_NOCACHE | BUS_DMA_WAITOK, &vbp->dmamap)) goto out_err; - bus_dmamap_load(mp->dmat, vbp->dmamap, vaddr, - MEMO_CLUSTER_SIZE, getbaddrcb, &baddr, BUS_DMA_NOWAIT); + bus_dmamap_load(mp->dmat, vbp->dmamap, vaddr, MEMO_CLUSTER_SIZE, + getbaddrcb, &baddr, BUS_DMA_NOWAIT); if (baddr) { int hc = VTOB_HASH_CODE(vaddr); vbp->vaddr = (m_addr_t) vaddr; @@ -1484,7 +1481,7 @@ struct sym_hcb { u32 scr_ram_seg; /* - * Chip and controller indentification. + * Chip and controller identification. */ device_t device; @@ -1534,7 +1531,6 @@ struct sym_hcb { struct resource *io_res; struct resource *mmio_res; struct resource *ram_res; - int ram_id; void *intr; /* @@ -1558,8 +1554,6 @@ struct sym_hcb { * BUS addresses of the chip */ vm_offset_t mmio_ba; /* MMIO BUS address */ - int mmio_ws; /* MMIO Window size */ - vm_offset_t ram_ba; /* RAM BUS address */ int ram_ws; /* RAM window size */ @@ -2012,8 +2006,8 @@ static void sym_fw_bind_script (hcb_p np, u32 *start, int len) * command. */ if (opcode == 0) { - printf ("%s: ERROR0 IN SCRIPT at %d.\n", - sym_name(np), (int) (cur-start)); + device_printf(np->device, "ERROR0 IN SCRIPT at %d.\n", + (int)(cur-start)); MDELAY (10000); ++cur; continue; @@ -2056,8 +2050,9 @@ static void sym_fw_bind_script (hcb_p np, u32 *start, int len) tmp1 = cur[1]; tmp2 = cur[2]; if ((tmp1 ^ tmp2) & 3) { - printf ("%s: ERROR1 IN SCRIPT at %d.\n", - sym_name(np), (int) (cur-start)); + device_printf(np->device, + "ERROR1 IN SCRIPT at %d.\n", + (int)(cur-start)); MDELAY (10000); } /* @@ -2248,10 +2243,11 @@ static void sym_update_dflags(hcb_p np, u_char *flags, struct ccb_trans_settings *cts); static const struct sym_pci_chip *sym_find_pci_chip (device_t dev); -static int sym_pci_probe (device_t dev); -static int sym_pci_attach (device_t dev); -static void sym_pci_free (hcb_p np); +static device_probe_t sym_pci_probe; +static device_attach_t sym_pci_attach; +static device_detach_t sym_pci_detach; + static int sym_cam_attach (hcb_p np); static void sym_cam_free (hcb_p np); @@ -2426,8 +2422,8 @@ static void sym_print_targets_flag(hcb_p np, int mask, char *msg) continue; if (np->target[i].usrflags & mask) { if (!cnt++) - printf("%s: %s disabled for targets", - sym_name(np), msg); + device_printf(np->device, + "%s disabled for targets", msg); printf(" %d", i); } } @@ -2750,41 +2746,42 @@ static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram) * Let user know about the settings. */ i = nvram->type; - printf("%s: %s NVRAM, ID %d, Fast-%d, %s, %s\n", sym_name(np), - i == SYM_SYMBIOS_NVRAM ? "Symbios" : - (i == SYM_TEKRAM_NVRAM ? "Tekram" : "No"), - np->myaddr, - (np->features & FE_ULTRA3) ? 80 : - (np->features & FE_ULTRA2) ? 40 : - (np->features & FE_ULTRA) ? 20 : 10, - sym_scsi_bus_mode(np->scsi_mode), - (np->rv_scntl0 & 0xa) ? "parity checking" : "NO parity"); + device_printf(np->device, "%s NVRAM, ID %d, Fast-%d, %s, %s\n", + i == SYM_SYMBIOS_NVRAM ? "Symbios" : + (i == SYM_TEKRAM_NVRAM ? "Tekram" : "No"), + np->myaddr, + (np->features & FE_ULTRA3) ? 80 : + (np->features & FE_ULTRA2) ? 40 : + (np->features & FE_ULTRA) ? 20 : 10, + sym_scsi_bus_mode(np->scsi_mode), + (np->rv_scntl0 & 0xa) ? "parity checking" : "NO parity"); /* * Tell him more on demand. */ if (sym_verbose) { - printf("%s: %s IRQ line driver%s\n", - sym_name(np), - np->rv_dcntl & IRQM ? "totem pole" : "open drain", - np->ram_ba ? ", using on-chip SRAM" : ""); - printf("%s: using %s firmware.\n", sym_name(np), np->fw_name); + device_printf(np->device, "%s IRQ line driver%s\n", + np->rv_dcntl & IRQM ? "totem pole" : "open drain", + np->ram_ba ? ", using on-chip SRAM" : ""); + device_printf(np->device, "using %s firmware.\n", np->fw_name); if (np->features & FE_NOPM) - printf("%s: handling phase mismatch from SCRIPTS.\n", - sym_name(np)); + device_printf(np->device, + "handling phase mismatch from SCRIPTS.\n"); } /* * And still more. */ if (sym_verbose > 1) { - printf ("%s: initial SCNTL3/DMODE/DCNTL/CTEST3/4/5 = " - "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n", - sym_name(np), np->sv_scntl3, np->sv_dmode, np->sv_dcntl, - np->sv_ctest3, np->sv_ctest4, np->sv_ctest5); + device_printf(np->device, + "initial SCNTL3/DMODE/DCNTL/CTEST3/4/5 = " + "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n", + np->sv_scntl3, np->sv_dmode, np->sv_dcntl, np->sv_ctest3, + np->sv_ctest4, np->sv_ctest5); - printf ("%s: final SCNTL3/DMODE/DCNTL/CTEST3/4/5 = " - "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n", - sym_name(np), np->rv_scntl3, np->rv_dmode, np->rv_dcntl, - np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); + device_printf(np->device, + "final SCNTL3/DMODE/DCNTL/CTEST3/4/5 = " + "(hex) %02x/%02x/%02x/%02x/%02x/%02x\n", + np->rv_scntl3, np->rv_dmode, np->rv_dcntl, + np->rv_ctest3, np->rv_ctest4, np->rv_ctest5); } /* * Let user be aware of targets that have some disable flags set. @@ -2911,7 +2908,7 @@ static void sym_put_start_queue(hcb_p np, ccb_p cp) np->squeueput = qidx; if (DEBUG_FLAGS & DEBUG_QUEUE) - printf ("%s: queuepos=%d.\n", sym_name (np), np->squeueput); + device_printf(np->device, "queuepos=%d.\n", np->squeueput); /* * Script processor may be waiting for reselect. @@ -2965,8 +2962,8 @@ static void sym_soft_reset (hcb_p np) } } if (!i) - printf("%s: unable to abort current chip operation.\n", - sym_name(np)); + device_printf(np->device, + "unable to abort current chip operation.\n"); sym_chip_reset (np); } @@ -3016,13 +3013,12 @@ static int sym_reset_scsi_bus(hcb_p np, int enab_int) term &= 0x3ffff; if (term != (2<<7)) { - printf("%s: suspicious SCSI data while resetting the BUS.\n", - sym_name(np)); - printf("%s: %sdp0,d7-0,rst,req,ack,bsy,sel,atn,msg,c/d,i/o = " - "0x%lx, expecting 0x%lx\n", - sym_name(np), - (np->features & FE_WIDE) ? "dp1,d15-8," : "", - (u_long)term, (u_long)(2<<7)); + device_printf(np->device, + "suspicious SCSI data while resetting the BUS.\n"); + device_printf(np->device, + "%sdp0,d7-0,rst,req,ack,bsy,sel,atn,msg,c/d,i/o = " + "0x%lx, expecting 0x%lx\n", (np->features & FE_WIDE) ? + "dp1,d15-8," : "", (u_long)term, (u_long)(2 << 7)); if (SYM_SETUP_SCSI_BUS_CHECK == 1) retv = 1; } @@ -3062,10 +3058,9 @@ static int sym_wakeup_done (hcb_p np) MEMORY_BARRIER(); sym_complete_ok (np, cp); ++n; - } - else - printf ("%s: bad DSA (%x) in done queue.\n", - sym_name(np), (u_int) dsa); + } else + device_printf(np->device, + "bad DSA (%x) in done queue.\n", (u_int)dsa); } np->dqueueget = i; @@ -3286,8 +3281,8 @@ static void sym_init (hcb_p np, int reason) */ if (np->ram_ba) { if (sym_verbose > 1) - printf ("%s: Downloading SCSI SCRIPTS.\n", - sym_name(np)); + device_printf(np->device, + "Downloading SCSI SCRIPTS.\n"); if (np->ram_ws == 8192) { OUTRAM_OFF(4096, np->scriptb0, np->scriptb_sz); OUTL (nc_mmws, np->scr_ram_seg); @@ -3710,11 +3705,11 @@ static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat) if (((script_ofs & 3) == 0) && (unsigned)script_ofs < script_size) { - printf ("%s: script cmd = %08x\n", sym_name(np), - scr_to_cpu((int) *(u32 *)(script_base + script_ofs))); + device_printf(np->device, "script cmd = %08x\n", + scr_to_cpu((int) *(u32 *)(script_base + script_ofs))); } - printf ("%s: regdump:", sym_name(np)); + device_printf(np->device, "regdump:"); for (i = 0; i < 24; i++) printf (" %02x", (unsigned)INB_OFF(i)); printf (".\n"); @@ -3727,8 +3722,8 @@ static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat) pci_sts = pci_read_config(np->device, PCIR_STATUS, 2); if (pci_sts & 0xf900) { pci_write_config(np->device, PCIR_STATUS, pci_sts, 2); - printf("%s: PCI STATUS = 0x%04x\n", - sym_name(np), pci_sts & 0xf900); + device_printf(np->device, "PCI STATUS = 0x%04x\n", + pci_sts & 0xf900); } } } @@ -3933,9 +3928,9 @@ unknown_int: * We just miss the cause of the interrupt. :( * Print a message. The timeout will do the real work. */ - printf( "%s: unknown interrupt(s) ignored, " - "ISTAT=0x%x DSTAT=0x%x SIST=0x%x\n", - sym_name(np), istat, dstat, sist); + device_printf(np->device, + "unknown interrupt(s) ignored, ISTAT=0x%x DSTAT=0x%x SIST=0x%x\n", + istat, dstat, sist); } static void sym_intr(void *arg) @@ -4050,7 +4045,7 @@ static void sym_int_sto (hcb_p np) */ static void sym_int_udc (hcb_p np) { - printf ("%s: unexpected disconnect\n", sym_name(np)); + device_printf(np->device, "unexpected disconnect\n"); sym_recover_scsi_int(np, HS_UNEXPECTED); } @@ -4117,8 +4112,9 @@ static void sym_int_par (hcb_p np, u_short sist) int phase = cmd & 7; ccb_p cp = sym_ccb_from_dsa(np, dsa); - printf("%s: SCSI parity error detected: SCR1=%d DBC=%x SBCL=%x\n", - sym_name(np), hsts, dbc, sbcl); + device_printf(np->device, + "SCSI parity error detected: SCR1=%d DBC=%x SBCL=%x\n", hsts, dbc, + sbcl); /* * Check that the chip is connected to the SCSI BUS. @@ -4305,14 +4301,14 @@ static void sym_int_ma (hcb_p np) } if (!vdsp) { - printf ("%s: interrupted SCRIPT address not found.\n", - sym_name (np)); + device_printf(np->device, + "interrupted SCRIPT address not found.\n"); goto reset_all; } if (!cp) { - printf ("%s: SCSI phase error fixup: CCB already dequeued.\n", - sym_name (np)); + device_printf(np->device, + "SCSI phase error fixup: CCB already dequeued.\n"); goto reset_all; } @@ -6757,15 +6753,15 @@ restart_test: dstat = INB (nc_dstat); #if 1 /* Band aiding for broken hardwares that fail PCI parity */ if ((dstat & MDPE) && (np->rv_ctest4 & MPEE)) { - printf ("%s: PCI DATA PARITY ERROR DETECTED - " - "DISABLING MASTER DATA PARITY CHECKING.\n", - sym_name(np)); + device_printf(np->device, "PCI DATA PARITY ERROR DETECTED - " + "DISABLING MASTER DATA PARITY CHECKING.\n"); np->rv_ctest4 &= ~MPEE; goto restart_test; } #endif if (dstat & (MDPE|BF|IID)) { - printf ("CACHE TEST FAILED: DMA error (dstat=0x%02x).", dstat); + device_printf(np->device, + "CACHE TEST FAILED: DMA error (dstat=0x%02x).\n", dstat); return (0x80); } /* @@ -6783,28 +6779,32 @@ restart_test: * Check termination position. */ if (pc != SCRIPTB0_BA (np, snoopend)+8) { - printf ("CACHE TEST FAILED: script execution failed.\n"); - printf ("start=%08lx, pc=%08lx, end=%08lx\n", - (u_long) SCRIPTB0_BA (np, snooptest), (u_long) pc, - (u_long) SCRIPTB0_BA (np, snoopend) +8); + device_printf(np->device, + "CACHE TEST FAILED: script execution failed.\n"); + device_printf(np->device, "start=%08lx, pc=%08lx, end=%08lx\n", + (u_long)SCRIPTB0_BA(np, snooptest), (u_long)pc, + (u_long)SCRIPTB0_BA(np, snoopend) + 8); return (0x40); } /* * Show results. */ if (host_wr != sym_rd) { - printf ("CACHE TEST FAILED: host wrote %d, chip read %d.\n", - (int) host_wr, (int) sym_rd); + device_printf(np->device, + "CACHE TEST FAILED: host wrote %d, chip read %d.\n", + (int)host_wr, (int)sym_rd); err |= 1; } if (host_rd != sym_wr) { - printf ("CACHE TEST FAILED: chip wrote %d, host read %d.\n", - (int) sym_wr, (int) host_rd); + device_printf(np->device, + "CACHE TEST FAILED: chip wrote %d, host read %d.\n", + (int)sym_wr, (int)host_rd); err |= 2; } if (sym_bk != sym_wr) { - printf ("CACHE TEST FAILED: chip wrote %d, read back %d.\n", - (int) sym_wr, (int) sym_bk); + device_printf(np->device, + "CACHE TEST FAILED: chip wrote %d, read back %d.\n", + (int)sym_wr, (int)sym_bk); err |= 4; } @@ -6843,7 +6843,7 @@ static void sym_selectclock(hcb_p np, u_char scntl3) } if (sym_verbose >= 2) - printf ("%s: enabling clock multiplier\n", sym_name(np)); + device_printf(np->device, "enabling clock multiplier\n"); OUTB(nc_stest1, DBLEN); /* Enable clock multiplier */ /* @@ -6855,8 +6855,8 @@ static void sym_selectclock(hcb_p np, u_char scntl3) while (!(INB(nc_stest4) & LCKFRQ) && --i > 0) UDELAY (20); if (!i) - printf("%s: the chip cannot lock the frequency\n", - sym_name(np)); + device_printf(np->device, + "the chip cannot lock the frequency\n"); } else UDELAY (20); OUTB(nc_stest3, HSC); /* Halt the scsi clock */ @@ -6911,8 +6911,8 @@ static unsigned getfreq (hcb_p np, int gen) f = ms ? ((1 << gen) * 4340) / ms : 0; if (sym_verbose >= 2) - printf ("%s: Delay (GEN=%d): %u msec, %u KHz\n", - sym_name(np), gen, ms, f); + device_printf(np->device, "Delay (GEN=%d): %u msec, %u KHz\n", + gen, ms, f); return f; } @@ -6954,7 +6954,7 @@ static void sym_getclock (hcb_p np, int mult) */ if (mult > 1 && (stest1 & (DBLEN+DBLSEL)) == DBLEN+DBLSEL) { if (sym_verbose >= 2) - printf ("%s: clock multiplier found\n", sym_name(np)); + device_printf(np->device, "clock multiplier found\n"); np->multiplier = mult; } @@ -6968,7 +6968,7 @@ static void sym_getclock (hcb_p np, int mult) f1 = sym_getfreq (np); if (sym_verbose) - printf ("%s: chip clock is %uKHz\n", sym_name(np), f1); + device_printf(np->device, "chip clock is %uKHz\n", f1); if (f1 < 45000) f1 = 40000; else if (f1 < 55000) f1 = 50000; @@ -6976,8 +6976,8 @@ static void sym_getclock (hcb_p np, int mult) if (f1 < 80000 && mult > 1) { if (sym_verbose >= 2) - printf ("%s: clock multiplier assumed\n", - sym_name(np)); + device_printf(np->device, + "clock multiplier assumed\n"); np->multiplier = mult; } } else { @@ -7146,7 +7146,7 @@ static void sym_complete_error (hcb_p np, ccb_p cp) sense_returned; else csio->sense_resid = 0; - bcopy(cp->sns_bbuf, &csio->sense_data, + memcpy(&csio->sense_data, cp->sns_bbuf, MIN(csio->sense_len, sense_returned)); #if 0 /* @@ -7631,7 +7631,7 @@ static int sym_setup_cdb(hcb_p np, struct ccb_scsiio *csio, ccb_p cp) /* CDB is a pointer */ if (!(ccb_h->flags & CAM_CDB_PHYS)) { /* CDB pointer is virtual */ - bcopy(csio->cdb_io.cdb_ptr, cp->cdb_buf, cmd_len); + memcpy(cp->cdb_buf, csio->cdb_io.cdb_ptr, cmd_len); cmd_ba = CCB_BA (cp, cdb_buf[0]); } else { /* CDB pointer is physical */ @@ -7644,7 +7644,7 @@ static int sym_setup_cdb(hcb_p np, struct ccb_scsiio *csio, ccb_p cp) } } else { /* CDB is in the CAM ccb (buffer) */ - bcopy(csio->cdb_io.cdb_bytes, cp->cdb_buf, cmd_len); + memcpy(cp->cdb_buf, csio->cdb_io.cdb_bytes, cmd_len); cmd_ba = CCB_BA (cp, cdb_buf[0]); } @@ -7858,9 +7858,9 @@ sym_fast_scatter_sg_physical(hcb_p np, ccb_p cp, data->addr = cpu_to_scr(psegs2->ds_addr); data->size = cpu_to_scr(psegs2->ds_len); if (DEBUG_FLAGS & DEBUG_SCATTER) { - printf ("%s scatter: paddr=%lx len=%ld\n", - sym_name(np), (long) psegs2->ds_addr, - (long) psegs2->ds_len); + device_printf(np->device, + "scatter: paddr=%lx len=%ld\n", + (long)psegs2->ds_addr, (long)psegs2->ds_len); } if (psegs2 != psegs) { --data; @@ -7895,8 +7895,8 @@ sym_scatter_sg_physical(hcb_p np, ccb_p cp, bus_dma_segment_t *psegs, int nsegs) pn = ps; k = pe - pn; if (DEBUG_FLAGS & DEBUG_SCATTER) { - printf ("%s scatter: paddr=%lx len=%ld\n", - sym_name(np), pn, k); + device_printf(np->device, + "scatter: paddr=%lx len=%ld\n", pn, k); } cp->phys.data[s].addr = cpu_to_scr(pn); cp->phys.data[s].size = cpu_to_scr(k); @@ -8232,6 +8232,7 @@ sym_update_dflags(hcb_p np, u_char *flags, struct ccb_trans_settings *cts) static device_method_t sym_pci_methods[] = { DEVMETHOD(device_probe, sym_pci_probe), DEVMETHOD(device_attach, sym_pci_attach), + DEVMETHOD(device_detach, sym_pci_detach), DEVMETHOD_END }; @@ -8521,16 +8522,15 @@ sym_pci_attach(device_t dev) * Alloc/get/map/retrieve the corresponding resources. */ if (np->features & (FE_RAM|FE_RAM8K)) { - int regs_id = SYM_PCI_RAM; + i = SYM_PCI_RAM; if (np->features & FE_64BIT) - regs_id = SYM_PCI_RAM64; - np->ram_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, - ®s_id, RF_ACTIVE); + i = SYM_PCI_RAM64; + np->ram_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i, + RF_ACTIVE); if (!np->ram_res) { device_printf(dev,"failed to allocate RAM resources\n"); goto attach_failed; } - np->ram_id = regs_id; np->ram_ba = rman_get_start(np->ram_res); } @@ -8631,8 +8631,8 @@ sym_pci_attach(device_t dev) /* * Copy scripts to controller instance. */ - bcopy(fw->a_base, np->scripta0, np->scripta_sz); - bcopy(fw->b_base, np->scriptb0, np->scriptb_sz); + memcpy(np->scripta0, fw->a_base, np->scripta_sz); + memcpy(np->scriptb0, fw->b_base, np->scriptb_sz); /* * Setup variable parts in scripts and compute @@ -8735,21 +8735,25 @@ sym_pci_attach(device_t dev) */ attach_failed: if (np) - sym_pci_free(np); + sym_pci_detach(dev); return ENXIO; } /* - * Free everything that have been allocated for this device. + * Detach a device by freeing everything that has been allocated for it. */ -static void sym_pci_free(hcb_p np) +static int +sym_pci_detach(device_t dev) { + hcb_p np; SYM_QUEHEAD *qp; ccb_p cp; tcb_p tp; lcb_p lp; int target, lun; + np = device_get_softc(dev); + /* * First free CAM resources. */ @@ -8761,16 +8765,15 @@ static void sym_pci_free(hcb_p np) */ if (np->ram_res) bus_release_resource(np->device, SYS_RES_MEMORY, - np->ram_id, np->ram_res); + rman_get_rid(np->ram_res), np->ram_res); if (np->mmio_res) bus_release_resource(np->device, SYS_RES_MEMORY, - SYM_PCI_MMIO, np->mmio_res); + rman_get_rid(np->mmio_res), np->mmio_res); if (np->io_res) bus_release_resource(np->device, SYS_RES_IOPORT, - SYM_PCI_IO, np->io_res); + rman_get_rid(np->io_res), np->io_res); if (np->irq_res) - bus_release_resource(np->device, SYS_RES_IRQ, - 0, np->irq_res); + bus_release_resource(np->device, SYS_RES_IRQ, 0, np->irq_res); if (np->scriptb0) sym_mfree_dma(np->scriptb0, np->scriptb_sz, "SCRIPTB0"); @@ -8824,6 +8827,8 @@ static void sym_pci_free(hcb_p np) SYM_LOCK_DESTROY(); device_set_softc(np->device, NULL); sym_mfree_dma(np, sizeof(*np), "HCB"); + + return (0); } /* @@ -8897,11 +8902,6 @@ static int sym_cam_attach(hcb_p np) return 1; fail: - if (sim) - cam_sim_free(sim, FALSE); - if (devq) - cam_simq_free(devq); - SYM_UNLOCK(); sym_cam_free(np); @@ -8924,15 +8924,16 @@ static void sym_cam_free(hcb_p np) SYM_LOCK(); + if (np->path) { + xpt_async(AC_LOST_DEVICE, np->path, NULL); + xpt_free_path(np->path); + np->path = NULL; + } if (np->sim) { xpt_bus_deregister(cam_sim_path(np->sim)); cam_sim_free(np->sim, /*free_devq*/ TRUE); np->sim = NULL; } - if (np->path) { - xpt_free_path(np->path); - np->path = NULL; - } SYM_UNLOCK(); } @@ -9057,14 +9058,14 @@ static void sym_display_Symbios_nvram(hcb_p np, Symbios_nvram *nvram) int i; /* display Symbios nvram host data */ - printf("%s: HOST ID=%d%s%s%s%s%s%s\n", - sym_name(np), nvram->host_id & 0x0f, - (nvram->flags & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"", - (nvram->flags & SYMBIOS_PARITY_ENABLE) ? " PARITY" :"", - (nvram->flags & SYMBIOS_VERBOSE_MSGS) ? " VERBOSE" :"", - (nvram->flags & SYMBIOS_CHS_MAPPING) ? " CHS_ALT" :"", - (nvram->flags2 & SYMBIOS_AVOID_BUS_RESET)?" NO_RESET" :"", - (nvram->flags1 & SYMBIOS_SCAN_HI_LO) ? " HI_LO" :""); + device_printf(np->device, "HOST ID=%d%s%s%s%s%s%s\n", + nvram->host_id & 0x0f, + (nvram->flags & SYMBIOS_SCAM_ENABLE) ? " SCAM" : "", + (nvram->flags & SYMBIOS_PARITY_ENABLE) ? " PARITY" : "", + (nvram->flags & SYMBIOS_VERBOSE_MSGS) ? " VERBOSE" : "", + (nvram->flags & SYMBIOS_CHS_MAPPING) ? " CHS_ALT" : "", + (nvram->flags2 & SYMBIOS_AVOID_BUS_RESET) ? " NO_RESET" : "", + (nvram->flags1 & SYMBIOS_SCAN_HI_LO) ? " HI_LO" : ""); /* display Symbios nvram drive data */ for (i = 0 ; i < 15 ; i++) { @@ -9102,17 +9103,18 @@ static void sym_display_Tekram_nvram(hcb_p np, Tekram_nvram *nvram) case 2: rem = " REMOVABLE=all"; break; } - printf("%s: HOST ID=%d%s%s%s%s%s%s%s%s%s BOOT DELAY=%d tags=%d\n", - sym_name(np), nvram->host_id & 0x0f, - (nvram->flags1 & SYMBIOS_SCAM_ENABLE) ? " SCAM" :"", - (nvram->flags & TEKRAM_MORE_THAN_2_DRIVES) ? " >2DRIVES" :"", - (nvram->flags & TEKRAM_DRIVES_SUP_1GB) ? " >1GB" :"", - (nvram->flags & TEKRAM_RESET_ON_POWER_ON) ? " RESET" :"", - (nvram->flags & TEKRAM_ACTIVE_NEGATION) ? " ACT_NEG" :"", - (nvram->flags & TEKRAM_IMMEDIATE_SEEK) ? " IMM_SEEK" :"", - (nvram->flags & TEKRAM_SCAN_LUNS) ? " SCAN_LUNS" :"", - (nvram->flags1 & TEKRAM_F2_F6_ENABLED) ? " F2_F6" :"", - rem, boot_delay, tags); + device_printf(np->device, + "HOST ID=%d%s%s%s%s%s%s%s%s%s BOOT DELAY=%d tags=%d\n", + nvram->host_id & 0x0f, + (nvram->flags1 & SYMBIOS_SCAM_ENABLE) ? " SCAM" : "", + (nvram->flags & TEKRAM_MORE_THAN_2_DRIVES) ? " >2DRIVES" : "", + (nvram->flags & TEKRAM_DRIVES_SUP_1GB) ? " >1GB" : "", + (nvram->flags & TEKRAM_RESET_ON_POWER_ON) ? " RESET" : "", + (nvram->flags & TEKRAM_ACTIVE_NEGATION) ? " ACT_NEG" : "", + (nvram->flags & TEKRAM_IMMEDIATE_SEEK) ? " IMM_SEEK" : "", + (nvram->flags & TEKRAM_SCAN_LUNS) ? " SCAN_LUNS" : "", + (nvram->flags1 & TEKRAM_F2_F6_ENABLED) ? " F2_F6" : "", + rem, boot_delay, tags); /* display Tekram nvram drive data */ for (i = 0; i <= 15; i++) { diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index e9d664f51a1f..1a2969d6f2d8 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -3987,10 +3987,10 @@ next_code: break; case SUSP: - power_pm_suspend(POWER_SLEEP_STATE_SUSPEND); + power_pm_suspend(POWER_SSTATE_TRANSITION_SUSPEND); break; case STBY: - power_pm_suspend(POWER_SLEEP_STATE_STANDBY); + power_pm_suspend(POWER_SSTATE_TRANSITION_STANDBY); break; case DBG: diff --git a/sys/dev/tdfx/tdfx_pci.c b/sys/dev/tdfx/tdfx_pci.c index d73ec841f333..98b32e353c93 100644 --- a/sys/dev/tdfx/tdfx_pci.c +++ b/sys/dev/tdfx/tdfx_pci.c @@ -83,7 +83,7 @@ static device_method_t tdfx_methods[] = { DEVMETHOD(device_attach, tdfx_attach), DEVMETHOD(device_detach, tdfx_detach), DEVMETHOD(device_shutdown, tdfx_shutdown), - { 0, 0 } + DEVMETHOD_END }; static MALLOC_DEFINE(M_TDFX,"tdfx_driver","3DFX Graphics[/2D]/3D Accelerators"); diff --git a/sys/dev/thunderbolt/nhi.c b/sys/dev/thunderbolt/nhi.c index 30a72652535a..9550de258dab 100644 --- a/sys/dev/thunderbolt/nhi.c +++ b/sys/dev/thunderbolt/nhi.c @@ -84,11 +84,6 @@ MALLOC_DEFINE(M_NHI, "nhi", "nhi driver memory"); #define NHI_DEBUG_LEVEL 0 #endif -/* 0 = default, 1 = force-on, 2 = force-off */ -#ifndef NHI_FORCE_HCM -#define NHI_FORCE_HCM 0 -#endif - void nhi_get_tunables(struct nhi_softc *sc) { @@ -100,7 +95,6 @@ nhi_get_tunables(struct nhi_softc *sc) /* Set local defaults */ sc->debug = NHI_DEBUG_LEVEL; sc->max_ring_count = NHI_DEFAULT_NUM_RINGS; - sc->force_hcm = NHI_FORCE_HCM; /* Inherit setting from the upstream thunderbolt switch node */ val = TB_GET_DEBUG(sc->dev, &sc->debug); @@ -128,8 +122,6 @@ nhi_get_tunables(struct nhi_softc *sc) val = min(val, NHI_MAX_NUM_RINGS); sc->max_ring_count = max(val, 1); } - if (TUNABLE_INT_FETCH("hw.nhi.force_hcm", &val) != 0) - sc->force_hcm = val; /* Grab instance variables */ bzero(oid, 80); @@ -143,24 +135,10 @@ nhi_get_tunables(struct nhi_softc *sc) val = min(val, NHI_MAX_NUM_RINGS); sc->max_ring_count = max(val, 1); } - snprintf(tmpstr, sizeof(tmpstr), "dev, nhi.%d.force_hcm", - device_get_unit(sc->dev)); - if (TUNABLE_INT_FETCH(tmpstr, &val) != 0) - sc->force_hcm = val; return; } -static void -nhi_configure_caps(struct nhi_softc *sc) -{ - - if (NHI_IS_USB4(sc) || (sc->force_hcm == NHI_FORCE_HCM_ON)) - sc->caps |= NHI_CAP_HCM; - if (sc->force_hcm == NHI_FORCE_HCM_OFF) - sc->caps &= ~NHI_CAP_HCM; -} - struct nhi_cmd_frame * nhi_alloc_tx_frame(struct nhi_ring_pair *r) { @@ -268,16 +246,14 @@ nhi_attach(struct nhi_softc *sc) mtx_init(&sc->nhi_mtx, "nhimtx", "NHI Control Mutex", MTX_DEF); - nhi_configure_caps(sc); - /* * Get the number of TX/RX paths. This sizes some of the register * arrays during allocation and initialization. USB4 spec says that - * the max is 21. Alpine Ridge appears to default to 12. + * the max is 21. */ val = GET_HOST_CAPS_PATHS(nhi_read_reg(sc, NHI_HOST_CAPS)); tb_debug(sc, DBG_INIT|DBG_NOISY, "Total Paths= %d\n", val); - if ((val == 0) || (val > 21) || ((NHI_IS_AR(sc) && val != 12))) { + if (val == 0 || val > 21) { tb_printf(sc, "WARN: unexpected number of paths: %d\n", val); /* return (ENXIO); */ } @@ -297,10 +273,6 @@ nhi_attach(struct nhi_softc *sc) if (error == 0) error = tbdev_add_interface(sc); - if ((error == 0) && (NHI_USE_ICM(sc))) - tb_printf(sc, "WARN: device uses an internal connection manager\n"); - if ((error == 0) && (NHI_USE_HCM(sc))) - ; error = hcm_attach(sc); if (error == 0) @@ -312,9 +284,7 @@ nhi_attach(struct nhi_softc *sc) int nhi_detach(struct nhi_softc *sc) { - - if (NHI_USE_HCM(sc)) - hcm_detach(sc); + hcm_detach(sc); if (sc->root_rsc != NULL) tb_router_detach(sc->root_rsc); @@ -601,7 +571,7 @@ nhi_alloc_ring0(struct nhi_softc *sc) TAILQ_INSERT_TAIL(&r->rx_head, cmd, cm_link); } - /* Inititalize the TX frames */ + /* Initialize the TX frames */ for ( ; i < r->tx_ring_depth + r->rx_ring_depth - 1; i++) { cmd = &sc->ring0_cmds[i]; cmd->data = (uint32_t *)(frames + NHI_RING0_FRAME_SIZE * i); @@ -706,16 +676,6 @@ nhi_init(struct nhi_softc *sc) tb_debug(sc, DBG_INIT, "Setting interrupt auto-ACK, 0x%08x\n", val); nhi_write_reg(sc, NHI_DMA_MISC, val); - if (NHI_IS_AR(sc) || NHI_IS_TR(sc) || NHI_IS_ICL(sc)) - tb_printf(sc, "WARN: device uses an internal connection manager\n"); - - /* - * Populate the controller (local) UUID, necessary for cross-domain - * communications. - if (NHI_IS_ICL(sc)) - nhi_pci_get_uuid(sc); - */ - /* * Attach the router to the root thunderbolt bridge now that the DMA * channel is configured and ready. @@ -1163,9 +1123,6 @@ nhi_setup_sysctl(struct nhi_softc *sc) SYSCTL_ADD_U16(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, "max_rings", CTLFLAG_RD, &sc->max_ring_count, 0, "Max number of rings available"); - SYSCTL_ADD_U8(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, - "force_hcm", CTLFLAG_RD, &sc->force_hcm, 0, - "Force on/off the function of the host connection manager"); return (0); } diff --git a/sys/dev/thunderbolt/nhi_pci.c b/sys/dev/thunderbolt/nhi_pci.c index 14cae7427448..777f8dd5352e 100644 --- a/sys/dev/thunderbolt/nhi_pci.c +++ b/sys/dev/thunderbolt/nhi_pci.c @@ -68,7 +68,6 @@ static int nhi_pci_resume(device_t); static void nhi_pci_free(struct nhi_softc *); static int nhi_pci_allocate_interrupts(struct nhi_softc *); static void nhi_pci_free_resources(struct nhi_softc *); -static int nhi_pci_icl_poweron(struct nhi_softc *); static device_method_t nhi_methods[] = { DEVMETHOD(device_probe, nhi_pci_probe), @@ -89,67 +88,18 @@ static driver_t nhi_pci_driver = { sizeof(struct nhi_softc) }; -struct nhi_ident { - uint16_t vendor; - uint16_t device; - uint16_t subvendor; - uint16_t subdevice; - uint32_t flags; - const char *desc; -} nhi_identifiers[] = { - { VENDOR_INTEL, DEVICE_AR_2C_NHI, 0xffff, 0xffff, NHI_TYPE_AR, - "Thunderbolt 3 NHI (Alpine Ridge 2C)" }, - { VENDOR_INTEL, DEVICE_AR_DP_B_NHI, 0xffff, 0xffff, NHI_TYPE_AR, - "Thunderbolt 3 NHI (Alpine Ridge 4C Rev B)" }, - { VENDOR_INTEL, DEVICE_AR_DP_C_NHI, 0xffff, 0xffff, NHI_TYPE_AR, - "Thunderbolt 3 NHI (Alpine Ridge 4C Rev C)" }, - { VENDOR_INTEL, DEVICE_AR_LP_NHI, 0xffff, 0xffff, NHI_TYPE_AR, - "Thunderbolt 3 NHI (Alpine Ridge LP 2C)" }, - { VENDOR_INTEL, DEVICE_ICL_NHI_0, 0xffff, 0xffff, NHI_TYPE_ICL, - "Thunderbolt 3 NHI Port 0 (IceLake)" }, - { VENDOR_INTEL, DEVICE_ICL_NHI_1, 0xffff, 0xffff, NHI_TYPE_ICL, - "Thunderbolt 3 NHI Port 1 (IceLake)" }, - { VENDOR_AMD, DEVICE_PINK_SARDINE_0, 0xffff, 0xffff, NHI_TYPE_USB4, - "USB4 NHI Port 0 (Pink Sardine)" }, - { VENDOR_AMD, DEVICE_PINK_SARDINE_1, 0xffff, 0xffff, NHI_TYPE_USB4, - "USB4 NHI Port 1 (Pink Sardine)" }, - { 0, 0, 0, 0, 0, NULL } -}; - DRIVER_MODULE_ORDERED(nhi, pci, nhi_pci_driver, NULL, NULL, SI_ORDER_ANY); -static struct nhi_ident * -nhi_find_ident(device_t dev) -{ - struct nhi_ident *n; - - for (n = nhi_identifiers; n->vendor != 0; n++) { - if (n->vendor != pci_get_vendor(dev)) - continue; - if (n->device != pci_get_device(dev)) - continue; - if ((n->subvendor != 0xffff) && - (n->subvendor != pci_get_subvendor(dev))) - continue; - if ((n->subdevice != 0xffff) && - (n->subdevice != pci_get_subdevice(dev))) - continue; - return (n); - } - - return (NULL); -} - static int nhi_pci_probe(device_t dev) { - struct nhi_ident *n; - if (resource_disabled("tb", 0)) return (ENXIO); - if ((n = nhi_find_ident(dev)) != NULL) { - device_set_desc(dev, n->desc); + if ((pci_get_class(dev) == PCIC_SERIALBUS) + && (pci_get_subclass(dev) == PCIS_SERIALBUS_USB) + && (pci_get_progif(dev) == PCIP_SERIALBUS_USB_USB4)) { + device_set_desc(dev, "Generic USB4 NHI"); return (BUS_PROBE_DEFAULT); } return (ENXIO); @@ -161,14 +111,12 @@ nhi_pci_attach(device_t dev) devclass_t dc; bus_dma_template_t t; struct nhi_softc *sc; - struct nhi_ident *n; int error = 0; sc = device_get_softc(dev); bzero(sc, sizeof(*sc)); sc->dev = dev; - n = nhi_find_ident(dev); - sc->hwflags = n->flags; + sc->hwflags = NHI_TYPE_USB4; nhi_get_tunables(sc); tb_debug(sc, DBG_INIT|DBG_FULL, "busmaster status was %s\n", @@ -188,12 +136,6 @@ nhi_pci_attach(device_t dev) tb_printf(sc, "Upstream Facing Port is %s\n", device_get_nameunit(sc->ufp)); - if (NHI_IS_ICL(sc)) { - if ((error = nhi_pci_icl_poweron(sc)) != 0) - return (error); - } - - /* Allocate BAR0 DMA registers */ sc->regs_rid = PCIR_BAR(0); if ((sc->regs_resource = bus_alloc_resource_any(dev, @@ -476,56 +418,3 @@ nhi_pci_disable_interrupts(struct nhi_softc *sc) nhi_read_reg(sc, NHI_ISR0); nhi_read_reg(sc, NHI_ISR1); } - -/* - * Icelake controllers need to be notified of power-on - */ -static int -nhi_pci_icl_poweron(struct nhi_softc *sc) -{ - device_t dev; - uint32_t val; - int i, error = 0; - - dev = sc->dev; - val = pci_read_config(dev, ICL_VSCAP_9, 4); - tb_debug(sc, DBG_INIT, "icl_poweron val= 0x%x\n", val); - if (val & ICL_VSCAP9_FWREADY) - return (0); - - val = pci_read_config(dev, ICL_VSCAP_22, 4); - val |= ICL_VSCAP22_FORCEPWR; - tb_debug(sc, DBG_INIT|DBG_FULL, "icl_poweron writing 0x%x\n", val); - pci_write_config(dev, ICL_VSCAP_22, val, 4); - - error = ETIMEDOUT; - for (i = 0; i < 15; i++) { - DELAY(1000000); - val = pci_read_config(dev, ICL_VSCAP_9, 4); - if (val & ICL_VSCAP9_FWREADY) { - error = 0; - break; - } - } - - return (error); -} - -/* - * Icelake and Alderlake controllers store their UUID in PCI config space - */ -int -nhi_pci_get_uuid(struct nhi_softc *sc) -{ - device_t dev; - uint32_t val[4]; - - dev = sc->dev; - val[0] = pci_read_config(dev, ICL_VSCAP_10, 4); - val[1] = pci_read_config(dev, ICL_VSCAP_11, 4); - val[2] = 0xffffffff; - val[3] = 0xffffffff; - - bcopy(val, &sc->uuid, 16); - return (0); -} diff --git a/sys/dev/thunderbolt/nhi_var.h b/sys/dev/thunderbolt/nhi_var.h index e79ecc954c1f..e22c0f4a2bae 100644 --- a/sys/dev/thunderbolt/nhi_var.h +++ b/sys/dev/thunderbolt/nhi_var.h @@ -142,19 +142,9 @@ struct nhi_softc { u_int debug; u_int hwflags; #define NHI_TYPE_UNKNOWN 0x00 -#define NHI_TYPE_AR 0x01 /* Alpine Ridge */ -#define NHI_TYPE_TR 0x02 /* Titan Ridge */ -#define NHI_TYPE_ICL 0x03 /* IceLake */ -#define NHI_TYPE_MR 0x04 /* Maple Ridge */ -#define NHI_TYPE_ADL 0x05 /* AlderLake */ #define NHI_TYPE_USB4 0x0f #define NHI_TYPE_MASK 0x0f #define NHI_MBOX_BUSY 0x10 - u_int caps; -#define NHI_CAP_ICM 0x01 -#define NHI_CAP_HCM 0x02 -#define NHI_USE_ICM(sc) ((sc)->caps & NHI_CAP_ICM) -#define NHI_USE_HCM(sc) ((sc)->caps & NHI_CAP_HCM) struct hcm_softc *hcm; struct router_softc *root_rsc; @@ -194,11 +184,6 @@ struct nhi_softc { struct intr_config_hook ich; - uint8_t force_hcm; -#define NHI_FORCE_HCM_DEFAULT 0x00 -#define NHI_FORCE_HCM_ON 0x01 -#define NHI_FORCE_HCM_OFF 0x02 - uint8_t uuid[16]; uint8_t lc_uuid[16]; }; @@ -209,9 +194,6 @@ struct nhi_dispatch { void *context; }; -#define NHI_IS_AR(sc) (((sc)->hwflags & NHI_TYPE_MASK) == NHI_TYPE_AR) -#define NHI_IS_TR(sc) (((sc)->hwflags & NHI_TYPE_MASK) == NHI_TYPE_TR) -#define NHI_IS_ICL(sc) (((sc)->hwflags & NHI_TYPE_MASK) == NHI_TYPE_ICL) #define NHI_IS_USB4(sc) (((sc)->hwflags & NHI_TYPE_MASK) == NHI_TYPE_USB4) int nhi_pci_configure_interrupts(struct nhi_softc *sc); diff --git a/sys/dev/thunderbolt/tb_pcib.c b/sys/dev/thunderbolt/tb_pcib.c index e6f0115364da..b30de5a7493c 100644 --- a/sys/dev/thunderbolt/tb_pcib.c +++ b/sys/dev/thunderbolt/tb_pcib.c @@ -90,18 +90,6 @@ struct tb_pcib_ident { uint32_t flags; /* This follows the tb_softc flags */ const char *desc; } tb_pcib_identifiers[] = { - { VENDOR_INTEL, TB_DEV_AR_2C, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_AR, - "Thunderbolt 3 PCI-PCI Bridge (Alpine Ridge 2C)" }, - { VENDOR_INTEL, TB_DEV_AR_LP, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_AR, - "Thunderbolt 3 PCI-PCI Bridge (Alpine Ridge LP)" }, - { VENDOR_INTEL, TB_DEV_AR_C_4C, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_AR, - "Thunderbolt 3 PCI-PCI Bridge (Alpine Ridge C 4C)" }, - { VENDOR_INTEL, TB_DEV_AR_C_2C, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_AR, - "Thunderbolt 3 PCI-PCI Bridge C (Alpine Ridge C 2C)" }, - { VENDOR_INTEL, TB_DEV_ICL_0, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_ICL, - "Thunderbolt 3 PCI-PCI Bridge (IceLake)" }, - { VENDOR_INTEL, TB_DEV_ICL_1, 0xffff, 0xffff, TB_GEN_TB3|TB_HWIF_ICL, - "Thunderbolt 3 PCI-PCI Bridge (IceLake)" }, { 0, 0, 0, 0, 0, NULL } }; @@ -119,6 +107,10 @@ tb_pcib_find_ident(device_t dev) for (n = tb_pcib_identifiers; n->vendor != 0; n++) { if ((n->vendor != v) || (n->device != d)) continue; + /* Only match actual PCI-PCI bridges to avoid conflict with NHI */ + if (pci_get_class(dev) != PCIC_BRIDGE || + pci_get_subclass(dev) != PCIS_BRIDGE_PCI) + continue; if (((n->subvendor != 0xffff) && (n->subvendor != sv)) || ((n->subdevice != 0xffff) && (n->subdevice != sd))) continue; diff --git a/sys/dev/ti/if_ti.c b/sys/dev/ti/if_ti.c index 14f7d353303f..a89a9d5b5422 100644 --- a/sys/dev/ti/if_ti.c +++ b/sys/dev/ti/if_ti.c @@ -261,7 +261,7 @@ static device_method_t ti_methods[] = { DEVMETHOD(device_attach, ti_attach), DEVMETHOD(device_detach, ti_detach), DEVMETHOD(device_shutdown, ti_shutdown), - { 0, 0 } + DEVMETHOD_END }; static driver_t ti_driver = { @@ -1635,10 +1635,10 @@ ti_newbuf_jumbo(struct ti_softc *sc, int idx, struct mbuf *m_old) } for (i = 0; i < NPAYLOAD; i++){ /* Attach the buffer to the mbuf. */ - m[i]->m_data = (void *)sf_buf_kva(sf[i]); + m[i]->m_data = sf_buf_kva(sf[i]); m[i]->m_len = PAGE_SIZE; MEXTADD(m[i], sf_buf_kva(sf[i]), PAGE_SIZE, - sf_mext_free, (void*)sf_buf_kva(sf[i]), sf[i], + sf_mext_free, sf_buf_kva(sf[i]), sf[i], 0, EXT_DISPOSABLE); m[i]->m_next = m[i+1]; } @@ -1703,7 +1703,7 @@ nobufs: if (m[i]) m_freem(m[i]); if (sf[i]) - sf_mext_free((void *)sf_buf_kva(sf[i]), sf[i]); + sf_mext_free(sf_buf_kva(sf[i]), sf[i]); } return (ENOBUFS); } diff --git a/sys/dev/tpm/tpm20.c b/sys/dev/tpm/tpm20.c index 6c587818058d..48f33708917d 100644 --- a/sys/dev/tpm/tpm20.c +++ b/sys/dev/tpm/tpm20.c @@ -41,10 +41,10 @@ MALLOC_DEFINE(M_TPM20, "tpm_buffer", "buffer for tpm 2.0 driver"); -static void tpm20_discard_buffer(void *arg); #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM static void tpm20_harvest(void *arg, int unused); #endif +static int tpm20_restart(device_t dev, bool clear); static int tpm20_save_state(device_t dev, bool suspend); static d_open_t tpm20_open; @@ -67,27 +67,23 @@ int tpm20_read(struct cdev *dev, struct uio *uio, int flags) { struct tpm_sc *sc; + struct tpm_priv *priv; size_t bytes_to_transfer; size_t offset; int result = 0; sc = (struct tpm_sc *)dev->si_drv1; + devfs_get_cdevpriv((void **)&priv); - callout_stop(&sc->discard_buffer_callout); sx_xlock(&sc->dev_lock); - if (sc->owner_tid != uio->uio_td->td_tid) { - sx_xunlock(&sc->dev_lock); - return (EPERM); - } - - bytes_to_transfer = MIN(sc->pending_data_length, uio->uio_resid); - offset = sc->total_length - sc->pending_data_length; + offset = priv->offset; + bytes_to_transfer = MIN(priv->len, uio->uio_resid); if (bytes_to_transfer > 0) { - result = uiomove((caddr_t) sc->buf + offset, bytes_to_transfer, uio); - sc->pending_data_length -= bytes_to_transfer; - cv_signal(&sc->buf_cv); + result = uiomove((caddr_t) priv->buf + offset, bytes_to_transfer, uio); + priv->offset += bytes_to_transfer; + priv->len -= bytes_to_transfer; } else { - result = ETIMEDOUT; + result = 0; } sx_xunlock(&sc->dev_lock); @@ -99,10 +95,12 @@ int tpm20_write(struct cdev *dev, struct uio *uio, int flags) { struct tpm_sc *sc; + struct tpm_priv *priv; size_t byte_count; int result = 0; sc = (struct tpm_sc *)dev->si_drv1; + devfs_get_cdevpriv((void **)&priv); byte_count = uio->uio_resid; if (byte_count < TPM_HEADER_SIZE) { @@ -119,52 +117,42 @@ tpm20_write(struct cdev *dev, struct uio *uio, int flags) sx_xlock(&sc->dev_lock); - while (sc->pending_data_length != 0) - cv_wait(&sc->buf_cv, &sc->dev_lock); - - result = uiomove(sc->buf, byte_count, uio); + result = uiomove(priv->buf, byte_count, uio); if (result != 0) { sx_xunlock(&sc->dev_lock); return (result); } - result = TPM_TRANSMIT(sc->dev, byte_count); - - if (result == 0) { - callout_reset(&sc->discard_buffer_callout, - TPM_READ_TIMEOUT / tick, tpm20_discard_buffer, sc); - sc->owner_tid = uio->uio_td->td_tid; - } + result = TPM_TRANSMIT(sc->dev, priv, byte_count); sx_xunlock(&sc->dev_lock); return (result); } -static void -tpm20_discard_buffer(void *arg) +static struct tpm_priv * +tpm20_priv_alloc(void) { - struct tpm_sc *sc; + struct tpm_priv *priv; - sc = (struct tpm_sc *)arg; - if (callout_pending(&sc->discard_buffer_callout)) - return; - - sx_xlock(&sc->dev_lock); - - memset(sc->buf, 0, TPM_BUFSIZE); - sc->pending_data_length = 0; - sc->total_length = 0; + priv = malloc(sizeof (*priv), M_TPM20, M_WAITOK | M_ZERO); + return (priv); +} - cv_signal(&sc->buf_cv); - sx_xunlock(&sc->dev_lock); +static void +tpm20_priv_dtor(void *data) +{ + struct tpm_priv *priv = data; - device_printf(sc->dev, - "User failed to read buffer in time\n"); + free(priv->buf, M_TPM20); } int tpm20_open(struct cdev *dev, int flag, int mode, struct thread *td) { + struct tpm_priv *priv; + + priv = tpm20_priv_alloc(); + devfs_set_cdevpriv(priv, tpm20_priv_dtor); return (0); } @@ -197,10 +185,7 @@ tpm20_init(struct tpm_sc *sc) struct make_dev_args args; int result; - cv_init(&sc->buf_cv, "TPM buffer cv"); - callout_init(&sc->discard_buffer_callout, 1); - sc->pending_data_length = 0; - sc->total_length = 0; + sc->internal_priv = tpm20_priv_alloc(); make_dev_args_init(&args); args.mda_devsw = &tpm20_cdevsw; @@ -233,18 +218,37 @@ tpm20_release(struct tpm_sc *sc) random_source_deregister(&random_tpm); #endif - if (sc->buf != NULL) - free(sc->buf, M_TPM20); - + tpm20_priv_dtor(sc->internal_priv); sx_destroy(&sc->dev_lock); - cv_destroy(&sc->buf_cv); if (sc->sc_cdev != NULL) destroy_dev(sc->sc_cdev); } int +tpm20_resume(device_t dev) +{ + + tpm20_restart(dev, false); + +#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM + struct tpm_sc *sc; + + sc = device_get_softc(dev); + taskqueue_enqueue_timeout(taskqueue_thread, &sc->harvest_task, + hz * TPM_HARVEST_INTERVAL); +#endif + return (0); +} + +int tpm20_suspend(device_t dev) { +#if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM + struct tpm_sc *sc; + + sc = device_get_softc(dev); + taskqueue_drain_timeout(taskqueue_thread, &sc->harvest_task); +#endif return (tpm20_save_state(dev, true)); } @@ -263,6 +267,7 @@ static void tpm20_harvest(void *arg, int unused) { struct tpm_sc *sc; + struct tpm_priv *priv; unsigned char entropy[TPM_HARVEST_SIZE]; uint16_t entropy_size; int result; @@ -275,26 +280,22 @@ tpm20_harvest(void *arg, int unused) sc = arg; sx_xlock(&sc->dev_lock); - while (sc->pending_data_length != 0) - cv_wait(&sc->buf_cv, &sc->dev_lock); - memcpy(sc->buf, cmd, sizeof(cmd)); - result = TPM_TRANSMIT(sc->dev, sizeof(cmd)); + priv = sc->internal_priv; + memcpy(priv->buf, cmd, sizeof(cmd)); + + result = TPM_TRANSMIT(sc->dev, priv, sizeof(cmd)); if (result != 0) { sx_xunlock(&sc->dev_lock); return; } - /* Ignore response size */ - sc->pending_data_length = 0; - sc->total_length = 0; - /* The number of random bytes we got is placed right after the header */ - entropy_size = (uint16_t) sc->buf[TPM_HEADER_SIZE + 1]; + entropy_size = (uint16_t) priv->buf[TPM_HEADER_SIZE + 1]; if (entropy_size > 0) { entropy_size = MIN(entropy_size, TPM_HARVEST_SIZE); memcpy(entropy, - sc->buf + TPM_HEADER_SIZE + sizeof(uint16_t), + priv->buf + TPM_HEADER_SIZE + sizeof(uint16_t), entropy_size); } @@ -308,9 +309,46 @@ tpm20_harvest(void *arg, int unused) #endif /* TPM_HARVEST */ static int +tpm20_restart(device_t dev, bool clear) +{ + struct tpm_sc *sc; + struct tpm_priv *priv; + uint8_t startup_cmd[] = { + 0x80, 0x01, /* TPM_ST_NO_SESSIONS tag*/ + 0x00, 0x00, 0x00, 0x0C, /* cmd length */ + 0x00, 0x00, 0x01, 0x44, /* cmd TPM_CC_Startup */ + 0x00, 0x01 /* TPM_SU_STATE */ + }; + + sc = device_get_softc(dev); + + /* + * Inform the TPM whether we are resetting or resuming. + */ + if (clear) + startup_cmd[11] = 0; /* TPM_SU_CLEAR */ + + if (sc == NULL) + return (0); + + sx_xlock(&sc->dev_lock); + + priv = sc->internal_priv; + memcpy(priv->buf, startup_cmd, sizeof(startup_cmd)); + + /* XXX Ignoring both TPM_TRANSMIT return and tpm's response */ + TPM_TRANSMIT(sc->dev, priv, sizeof(startup_cmd)); + + sx_xunlock(&sc->dev_lock); + + return (0); +} + +static int tpm20_save_state(device_t dev, bool suspend) { struct tpm_sc *sc; + struct tpm_priv *priv; uint8_t save_cmd[] = { 0x80, 0x01, /* TPM_ST_NO_SESSIONS tag*/ 0x00, 0x00, 0x00, 0x0C, /* cmd length */ @@ -326,13 +364,16 @@ tpm20_save_state(device_t dev, bool suspend) if (suspend) save_cmd[11] = 1; /* TPM_SU_STATE */ - if (sc == NULL || sc->buf == NULL) + if (sc == NULL) return (0); sx_xlock(&sc->dev_lock); - memcpy(sc->buf, save_cmd, sizeof(save_cmd)); - TPM_TRANSMIT(sc->dev, sizeof(save_cmd)); + priv = sc->internal_priv; + memcpy(priv->buf, save_cmd, sizeof(save_cmd)); + + /* XXX Ignoring both TPM_TRANSMIT return and tpm's response */ + TPM_TRANSMIT(sc->dev, priv, sizeof(save_cmd)); sx_xunlock(&sc->dev_lock); diff --git a/sys/dev/tpm/tpm20.h b/sys/dev/tpm/tpm20.h index b2cfcd4f25bd..b63bb9a1436e 100644 --- a/sys/dev/tpm/tpm20.h +++ b/sys/dev/tpm/tpm20.h @@ -105,6 +105,12 @@ MALLOC_DECLARE(M_TPM20); +struct tpm_priv { + uint8_t buf[TPM_BUFSIZE]; + size_t offset; + size_t len; +}; + struct tpm_sc { device_t dev; @@ -116,18 +122,13 @@ struct tpm_sc { struct cdev *sc_cdev; struct sx dev_lock; - struct cv buf_cv; void *intr_cookie; int intr_type; /* Current event type */ bool interrupts; - uint8_t *buf; - size_t pending_data_length; - size_t total_length; - lwpid_t owner_tid; + struct tpm_priv *internal_priv; - struct callout discard_buffer_callout; #if defined TPM_HARVEST || defined RANDOM_ENABLE_TPM struct timeout_task harvest_task; #endif @@ -136,6 +137,7 @@ struct tpm_sc { }; int tpm20_suspend(device_t dev); +int tpm20_resume(device_t dev); int tpm20_shutdown(device_t dev); int32_t tpm20_get_timeout(uint32_t command); int tpm20_init(struct tpm_sc *sc); diff --git a/sys/dev/tpm/tpm_acpi.c b/sys/dev/tpm/tpm_acpi.c index 1c7bb9a0175b..4d52b2952dd3 100644 --- a/sys/dev/tpm/tpm_acpi.c +++ b/sys/dev/tpm/tpm_acpi.c @@ -68,7 +68,7 @@ static device_method_t tpm_acpi_methods[] = { DEVMETHOD(device_detach, tpm_detach), DEVMETHOD(device_suspend, tpm_suspend), DEVMETHOD(device_resume, tpm_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t tpm_acpi_driver = { diff --git a/sys/dev/tpm/tpm_crb.c b/sys/dev/tpm/tpm_crb.c index 28b4f21eccfb..ac093c3857ba 100644 --- a/sys/dev/tpm/tpm_crb.c +++ b/sys/dev/tpm/tpm_crb.c @@ -75,15 +75,59 @@ #define TPM_CRB_INT_ENABLE_BIT BIT(31) +struct tpmcrb_sc; +/* Attach */ +typedef bool (sm_attach_t)(struct tpmcrb_sc *, void *, size_t); +/* State change notification (timeout == 0 for 'no timeout') */ +typedef bool (sm_statechange_t)(struct tpmcrb_sc *, int); + +struct tpmcrb_sm_cfg { + sm_attach_t *sm_attach; + sm_statechange_t *sm_statechange; + sm_statechange_t *sm_cmdready; +}; + +static sm_attach_t pluton_attach; +static sm_statechange_t pluton_doorbell; + +static const struct tpmcrb_sm_cfg_map { + int acpi_sm; + const char *desc; + const struct tpmcrb_sm_cfg sm_cfg; +} tpmcrb_sm_cfg_map[] = { + { + .acpi_sm = TPM2_START_METHOD_CRB, + .desc = "Trusted Platform Module 2.0, CRB mode", + .sm_cfg = { NULL }, /* No notifications required */ + }, + { + .acpi_sm = ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON, + .desc = "Trusted Platform Module 2.0, CRB mode (Pluton)", + .sm_cfg = { + .sm_attach = &pluton_attach, + .sm_statechange = &pluton_doorbell, + .sm_cmdready = &pluton_doorbell, + }, + }, +}; + struct tpmcrb_sc { struct tpm_sc base; + const struct tpmcrb_sm_cfg *sm_cfg; + union { + /* StartMethod data */ + struct { + uint64_t start_reg; + uint64_t reply_reg; + } pluton; + }; bus_size_t cmd_off; bus_size_t rsp_off; size_t cmd_buf_size; size_t rsp_buf_size; }; -int tpmcrb_transmit(device_t dev, size_t size); +int tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t size); static int tpmcrb_acpi_probe(device_t dev); static int tpmcrb_attach(device_t dev); @@ -99,23 +143,46 @@ static bool tpmcrb_cancel_cmd(struct tpm_sc *sc); char *tpmcrb_ids[] = {"MSFT0101", NULL}; +static const struct tpmcrb_sm_cfg_map * +tpmcrb_acpi_startmethod_cfg(int method) +{ + const struct tpmcrb_sm_cfg_map *entry; + + for (size_t i = 0; i < nitems(tpmcrb_sm_cfg_map); i++) { + entry = &tpmcrb_sm_cfg_map[i]; + + if (method == entry->acpi_sm) + return (entry); + } + + return (NULL); +} + static int tpmcrb_acpi_probe(device_t dev) { - int err; + int err, smethod; + const struct tpmcrb_sm_cfg_map *sm_cfg_map; ACPI_TABLE_TPM23 *tbl; ACPI_STATUS status; + err = ACPI_ID_PROBE(device_get_parent(dev), dev, tpmcrb_ids, NULL); if (err > 0) return (err); /*Find TPM2 Header*/ status = AcpiGetTable(ACPI_SIG_TPM2, 1, (ACPI_TABLE_HEADER **) &tbl); - if(ACPI_FAILURE(status) || - tbl->StartMethod != TPM2_START_METHOD_CRB) + if (ACPI_FAILURE(status)) + return (ENXIO); + + smethod = tbl->StartMethod; + AcpiPutTable((ACPI_TABLE_HEADER *)tbl); + + sm_cfg_map = tpmcrb_acpi_startmethod_cfg(smethod); + if (sm_cfg_map == NULL) return (ENXIO); - device_set_desc(dev, "Trusted Platform Module 2.0, CRB mode"); - return (err); + device_set_desc(dev, sm_cfg_map->desc); + return (0); } static ACPI_STATUS @@ -141,6 +208,40 @@ tpmcrb_fix_buff_offsets(ACPI_RESOURCE *res, void *arg) return (AE_OK); } +static bool +tpmcrb_attach_startmethod(struct tpmcrb_sc *crb_sc) +{ + const struct tpmcrb_sm_cfg_map *sm_cfg_map; + const struct tpmcrb_sm_cfg *sm_cfg; + ACPI_TABLE_TPM23 *tbl; + void *smdata; + ACPI_STATUS status; + bool ret; + + /* + * Grab what we need from the StartMethod. + */ + status = AcpiGetTable(ACPI_SIG_TPM2, 1, (ACPI_TABLE_HEADER **)(void **)&tbl); + if (ACPI_FAILURE(status)) + return (false); + + sm_cfg_map = tpmcrb_acpi_startmethod_cfg(tbl->StartMethod); + MPASS(sm_cfg_map != NULL); + sm_cfg = &sm_cfg_map->sm_cfg; + + crb_sc->sm_cfg = sm_cfg; + smdata = tbl + 1; + if (sm_cfg->sm_attach != NULL) { + ret = (*sm_cfg->sm_attach)(crb_sc, smdata, + tbl->Header.Length - sizeof(*tbl)); + } else { + ret = true; + } + + AcpiPutTable((ACPI_TABLE_HEADER *)tbl); + return (ret); +} + static int tpmcrb_attach(device_t dev) { @@ -156,7 +257,6 @@ tpmcrb_attach(device_t dev) sc->dev = dev; sx_init(&sc->dev_lock, "TPM driver lock"); - sc->buf = malloc(TPM_BUFSIZE, M_TPM20, M_WAITOK); sc->mem_rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, @@ -166,6 +266,11 @@ tpmcrb_attach(device_t dev) return (ENXIO); } + if (!tpmcrb_attach_startmethod(crb_sc)) { + tpmcrb_detach(dev); + return (ENXIO); + } + if(!tpmcrb_request_locality(sc, 0)) { tpmcrb_detach(dev); return (ENXIO); @@ -302,6 +407,30 @@ tpmcrb_cancel_cmd(struct tpm_sc *sc) } static bool +tpmcrb_notify_cmdready(struct tpmcrb_sc *crb_sc, int timeout) +{ + sm_statechange_t *cmdready_fn; + + cmdready_fn = crb_sc->sm_cfg->sm_cmdready; + if (cmdready_fn == NULL) + return (true); + + return ((*cmdready_fn)(crb_sc, timeout)); +} + +static bool +tpmcrb_notify_state_changing(struct tpmcrb_sc *crb_sc, int timeout) +{ + sm_statechange_t *statechange_fn; + + statechange_fn = crb_sc->sm_cfg->sm_statechange; + if (statechange_fn == NULL) + return (true); + + return ((*statechange_fn)(crb_sc, timeout)); +} + +static bool tpmcrb_state_idle(struct tpmcrb_sc *crb_sc, bool wait) { struct tpm_sc *sc; @@ -312,6 +441,9 @@ tpmcrb_state_idle(struct tpmcrb_sc *crb_sc, bool wait) sc = &crb_sc->base; OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_IDLE); + if (!tpmcrb_notify_state_changing(crb_sc, timeout)) + return (false); + if (timeout > 0) { mask = TPM_CRB_CTRL_STS_IDLE_BIT; if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, mask, mask, @@ -333,6 +465,9 @@ tpmcrb_state_ready(struct tpmcrb_sc *crb_sc, bool wait) sc = &crb_sc->base; OR4(sc, TPM_CRB_CTRL_REQ, TPM_CRB_CTRL_REQ_GO_READY); + if (!tpmcrb_notify_state_changing(crb_sc, timeout)) + return (false); + if (timeout > 0) { mask = TPM_CRB_CTRL_REQ_GO_READY; if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_STS, mask, !mask, @@ -344,7 +479,7 @@ tpmcrb_state_ready(struct tpmcrb_sc *crb_sc, bool wait) } int -tpmcrb_transmit(device_t dev, size_t length) +tpmcrb_transmit(device_t dev, struct tpm_priv *priv, size_t length) { struct tpmcrb_sc *crb_sc; struct tpm_sc *sc; @@ -395,17 +530,24 @@ tpmcrb_transmit(device_t dev, size_t length) * Calculate timeout for current command. * Command code is passed in bytes 6-10. */ - curr_cmd = be32toh(*(uint32_t *) (&sc->buf[6])); + curr_cmd = be32toh(*(uint32_t *) (&priv->buf[6])); timeout = tpm20_get_timeout(curr_cmd); /* Send command and tell device to process it. */ bus_write_region_stream_1(sc->mem_res, crb_sc->cmd_off, - sc->buf, length); + priv->buf, length); TPM_WRITE_BARRIER(dev, crb_sc->cmd_off, length); TPM_WRITE_4(dev, TPM_CRB_CTRL_START, TPM_CRB_CTRL_START_CMD); TPM_WRITE_BARRIER(dev, TPM_CRB_CTRL_START, 4); + if (!tpmcrb_notify_cmdready(crb_sc, timeout)) { + device_printf(dev, + "Timeout while waiting for device to ready\n"); + if (!tpmcrb_cancel_cmd(sc)) + return (EIO); + } + mask = ~0; if (!tpm_wait_for_u32(sc, TPM_CRB_CTRL_START, mask, ~mask, timeout)) { device_printf(dev, @@ -416,8 +558,8 @@ tpmcrb_transmit(device_t dev, size_t length) /* Read response header. Length is passed in bytes 2 - 6. */ bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off, - sc->buf, TPM_HEADER_SIZE); - bytes_available = be32toh(*(uint32_t *) (&sc->buf[2])); + priv->buf, TPM_HEADER_SIZE); + bytes_available = be32toh(*(uint32_t *) (&priv->buf[2])); if (bytes_available > TPM_BUFSIZE || bytes_available < TPM_HEADER_SIZE) { device_printf(dev, @@ -427,8 +569,12 @@ tpmcrb_transmit(device_t dev, size_t length) } bus_read_region_stream_1(sc->mem_res, crb_sc->rsp_off + TPM_HEADER_SIZE, - &sc->buf[TPM_HEADER_SIZE], bytes_available - TPM_HEADER_SIZE); + &priv->buf[TPM_HEADER_SIZE], bytes_available - TPM_HEADER_SIZE); + /* + * No need to wait for the transition to idle on the way out, we can + * relinquish locality right away. + */ if (!tpmcrb_state_idle(crb_sc, false)) { device_printf(dev, "Failed to transition to idle state post-send\n"); @@ -436,12 +582,67 @@ tpmcrb_transmit(device_t dev, size_t length) } tpmcrb_relinquish_locality(sc); - sc->pending_data_length = bytes_available; - sc->total_length = bytes_available; + priv->offset = 0; + priv->len = bytes_available; return (0); } +/* StartMethod Implementation Details */ + +/** Pluton **/ +struct tpmcrb_startmethod_pluton { + uint64_t sm_startaddr; + uint64_t sm_replyaddr; +}; + +static bool +pluton_attach(struct tpmcrb_sc *crb_sc, void *smdataregion, size_t datasz) +{ + struct tpmcrb_startmethod_pluton *smdata; + struct tpm_sc *sc; + rman_res_t base_addr, end_addr; + + if (datasz < sizeof(*smdata)) + return (false); + + smdata = smdataregion; + sc = &crb_sc->base; + + base_addr = rman_get_start(sc->mem_res); + end_addr = rman_get_end(sc->mem_res); + /* Sanity check */ + if (smdata->sm_startaddr < base_addr || + smdata->sm_startaddr > end_addr || + smdata->sm_replyaddr < base_addr || + smdata->sm_replyaddr > end_addr) + return (false); + + crb_sc->pluton.start_reg = smdata->sm_startaddr - base_addr; + crb_sc->pluton.reply_reg = smdata->sm_replyaddr - base_addr; + return (true); +} + +static bool +pluton_doorbell(struct tpmcrb_sc *crb_sc, int timeout) +{ + struct tpm_sc *sc; + device_t dev; + + sc = &crb_sc->base; + dev = sc->dev; + TPM_WRITE_4(dev, crb_sc->pluton.start_reg, 1); + TPM_WRITE_BARRIER(dev, crb_sc->pluton.start_reg, 4); + + if (timeout > 0) { + if (!tpm_wait_for_u32(sc, crb_sc->pluton.reply_reg, ~0U, 1, + timeout)) + return (false); + } + + return (true); +} + /* ACPI Driver */ static device_method_t tpmcrb_methods[] = { DEVMETHOD(device_probe, tpmcrb_acpi_probe), @@ -449,6 +650,7 @@ static device_method_t tpmcrb_methods[] = { DEVMETHOD(device_detach, tpmcrb_detach), DEVMETHOD(device_shutdown, tpm20_shutdown), DEVMETHOD(device_suspend, tpm20_suspend), + DEVMETHOD(device_resume, tpm20_resume), DEVMETHOD(tpm_transmit, tpmcrb_transmit), {0, 0} }; diff --git a/sys/dev/tpm/tpm_if.m b/sys/dev/tpm/tpm_if.m index b0149ba163a6..3b0dc9e3892f 100644 --- a/sys/dev/tpm/tpm_if.m +++ b/sys/dev/tpm/tpm_if.m @@ -28,6 +28,10 @@ #include <sys/bus.h> #include <dev/tpm/tpm20.h> +HEADER { + struct tpm_priv; +}; + INTERFACE tpm; # @@ -35,6 +39,7 @@ INTERFACE tpm; # METHOD int transmit { device_t dev; + struct tpm_priv *priv; size_t length; }; diff --git a/sys/dev/tpm/tpm_isa.c b/sys/dev/tpm/tpm_isa.c index 311246c16b49..6bb039c5af87 100644 --- a/sys/dev/tpm/tpm_isa.c +++ b/sys/dev/tpm/tpm_isa.c @@ -81,7 +81,7 @@ static device_method_t tpm_methods[] = { DEVMETHOD(device_detach, tpm_detach), DEVMETHOD(device_suspend, tpm_suspend), DEVMETHOD(device_resume, tpm_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t tpm_driver = { diff --git a/sys/dev/tpm/tpm_tis_core.c b/sys/dev/tpm/tpm_tis_core.c index 4159de4daf3b..f49a1f982e82 100644 --- a/sys/dev/tpm/tpm_tis_core.c +++ b/sys/dev/tpm/tpm_tis_core.c @@ -73,7 +73,7 @@ #define TPM_STS_BURST_MASK 0xFFFF00 #define TPM_STS_BURST_OFFSET 0x8 -static int tpmtis_transmit(device_t dev, size_t length); +static int tpmtis_transmit(device_t dev, struct tpm_priv *priv, size_t length); static int tpmtis_detach(device_t dev); @@ -104,7 +104,6 @@ tpmtis_attach(device_t dev) sc->intr_type = -1; sx_init(&sc->dev_lock, "TPM driver lock"); - sc->buf = malloc(TPM_BUFSIZE, M_TPM20, M_WAITOK); resource_int_value("tpm", device_get_unit(dev), "use_polling", &poll); if (poll != 0) { @@ -164,6 +163,7 @@ tpmtis_detach(device_t dev) static void tpmtis_test_intr(struct tpm_sc *sc) { + struct tpm_priv *priv; uint8_t cmd[] = { 0x80, 0x01, /* TPM_ST_NO_SESSIONS tag*/ 0x00, 0x00, 0x00, 0x0c, /* cmd length */ @@ -172,9 +172,9 @@ tpmtis_test_intr(struct tpm_sc *sc) }; sx_xlock(&sc->dev_lock); - memcpy(sc->buf, cmd, sizeof(cmd)); - tpmtis_transmit(sc->dev, sizeof(cmd)); - sc->pending_data_length = 0; + priv = sc->internal_priv; + memcpy(priv->buf, cmd, sizeof(cmd)); + tpmtis_transmit(sc->dev, priv, sizeof(cmd)); sx_xunlock(&sc->dev_lock); } @@ -384,7 +384,7 @@ tpmtis_go_ready(struct tpm_sc *sc) } static int -tpmtis_transmit(device_t dev, size_t length) +tpmtis_transmit(device_t dev, struct tpm_priv *priv, size_t length) { struct tpm_sc *sc; size_t bytes_available; @@ -404,7 +404,7 @@ tpmtis_transmit(device_t dev, size_t length) "Failed to switch to ready state\n"); return (EIO); } - if (!tpmtis_write_bytes(sc, length, sc->buf)) { + if (!tpmtis_write_bytes(sc, length, priv->buf)) { device_printf(dev, "Failed to write cmd to device\n"); return (EIO); @@ -428,7 +428,7 @@ tpmtis_transmit(device_t dev, size_t length) * Calculate timeout for current command. * Command code is passed in bytes 6-10. */ - curr_cmd = be32toh(*(uint32_t *) (&sc->buf[6])); + curr_cmd = be32toh(*(uint32_t *) (&priv->buf[6])); timeout = tpm20_get_timeout(curr_cmd); TPM_WRITE_4(dev, TPM_STS, TPM_STS_CMD_START); @@ -455,12 +455,12 @@ tpmtis_transmit(device_t dev, size_t length) return (EIO); } /* Read response header. Length is passed in bytes 2 - 6. */ - if(!tpmtis_read_bytes(sc, TPM_HEADER_SIZE, sc->buf)) { + if (!tpmtis_read_bytes(sc, TPM_HEADER_SIZE, priv->buf)) { device_printf(dev, "Failed to read response header\n"); return (EIO); } - bytes_available = be32toh(*(uint32_t *) (&sc->buf[2])); + bytes_available = be32toh(*(uint32_t *) (&priv->buf[2])); if (bytes_available > TPM_BUFSIZE || bytes_available < TPM_HEADER_SIZE) { device_printf(dev, @@ -468,15 +468,15 @@ tpmtis_transmit(device_t dev, size_t length) bytes_available); return (EIO); } - if(!tpmtis_read_bytes(sc, bytes_available - TPM_HEADER_SIZE, - &sc->buf[TPM_HEADER_SIZE])) { + if (!tpmtis_read_bytes(sc, bytes_available - TPM_HEADER_SIZE, + &priv->buf[TPM_HEADER_SIZE])) { device_printf(dev, "Failed to read response\n"); return (EIO); } tpmtis_relinquish_locality(sc); - sc->pending_data_length = bytes_available; - sc->total_length = bytes_available; + priv->offset = 0; + priv->len = bytes_available; return (0); } @@ -487,6 +487,7 @@ static device_method_t tpmtis_methods[] = { DEVMETHOD(device_detach, tpmtis_detach), DEVMETHOD(device_shutdown, tpm20_shutdown), DEVMETHOD(device_suspend, tpm20_suspend), + DEVMETHOD(device_resume, tpm20_resume), DEVMETHOD(tpm_transmit, tpmtis_transmit), DEVMETHOD_END }; diff --git a/sys/dev/uart/uart_bus_acpi.c b/sys/dev/uart/uart_bus_acpi.c index bd53bfb204ed..b75c8a9ad517 100644 --- a/sys/dev/uart/uart_bus_acpi.c +++ b/sys/dev/uart/uart_bus_acpi.c @@ -49,7 +49,7 @@ static device_method_t uart_acpi_methods[] = { DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), DEVMETHOD(device_resume, uart_bus_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t uart_acpi_driver = { diff --git a/sys/dev/uart/uart_bus_fdt.c b/sys/dev/uart/uart_bus_fdt.c index e9a7e04e4e0c..957638548880 100644 --- a/sys/dev/uart/uart_bus_fdt.c +++ b/sys/dev/uart/uart_bus_fdt.c @@ -54,7 +54,7 @@ static device_method_t uart_fdt_methods[] = { DEVMETHOD(device_probe, uart_fdt_probe), DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t uart_fdt_driver = { diff --git a/sys/dev/uart/uart_bus_isa.c b/sys/dev/uart/uart_bus_isa.c index 27211a1334c0..166f25599d4c 100644 --- a/sys/dev/uart/uart_bus_isa.c +++ b/sys/dev/uart/uart_bus_isa.c @@ -49,7 +49,7 @@ static device_method_t uart_isa_methods[] = { DEVMETHOD(device_attach, uart_bus_attach), DEVMETHOD(device_detach, uart_bus_detach), DEVMETHOD(device_resume, uart_bus_resume), - { 0, 0 } + DEVMETHOD_END }; static driver_t uart_isa_driver = { diff --git a/sys/dev/uart/uart_bus_pci.c b/sys/dev/uart/uart_bus_pci.c index 22af8ee8663c..97c5ff84d251 100644 --- a/sys/dev/uart/uart_bus_pci.c +++ b/sys/dev/uart/uart_bus_pci.c @@ -280,33 +280,43 @@ uart_pci_probe(device_t dev) { struct uart_softc *sc; const struct pci_id *id; - struct pci_id cid = { - .regshft = 0, - .rclk = 0, - .rid = 0x10 | PCI_NO_MSI, - .desc = "Generic SimpleComm PCI device", - }; - int result; sc = device_get_softc(dev); id = uart_pci_match(dev, pci_ns8250_ids); if (id != NULL) { sc->sc_class = &uart_ns8250_class; - goto match; + return (BUS_PROBE_SPECIFIC); } if (pci_get_class(dev) == PCIC_SIMPLECOMM && pci_get_subclass(dev) == PCIS_SIMPLECOMM_UART && - pci_get_progif(dev) < PCIP_SIMPLECOMM_UART_16550A) { - /* XXX rclk what to do */ - id = &cid; + pci_get_progif(dev) <= PCIP_SIMPLECOMM_UART_16550A) { sc->sc_class = &uart_ns8250_class; - goto match; + return (BUS_PROBE_GENERIC); } /* Add checks for non-ns8250 IDs here. */ return (ENXIO); +} + +static int +uart_pci_attach(device_t dev) +{ + static const struct pci_id cid = { + .regshft = 0, + .rclk = 0, + .rid = 0x10 | PCI_NO_MSI, + .desc = "Generic SimpleComm PCI device", + }; + struct uart_softc *sc; + const struct pci_id *id = uart_pci_match(dev, pci_ns8250_ids); + int count, result; + + if (id == NULL) + /* No specific PCI ID match, must be a generic device. */ + id = &cid; + + sc = device_get_softc(dev); - match: result = uart_bus_probe(dev, id->regshft, 0, id->rclk, id->rid & PCI_RID_MASK, 0, 0); /* Bail out on error. */ @@ -322,25 +332,13 @@ uart_pci_probe(device_t dev) /* Set/override the device description. */ if (id->desc) device_set_desc(dev, id->desc); - return (result); -} - -static int -uart_pci_attach(device_t dev) -{ - struct uart_softc *sc; - const struct pci_id *id; - int count; - - sc = device_get_softc(dev); /* - * Use MSI in preference to legacy IRQ if available. However, experience - * suggests this is only reliable when one MSI vector is advertised. + * Use MSI in preference to legacy IRQ if available. However, + * experience suggests this is only reliable when one MSI vector is + * advertised. */ - id = uart_pci_match(dev, pci_ns8250_ids); - if ((id == NULL || (id->rid & PCI_NO_MSI) == 0) && - pci_msi_count(dev) == 1) { + if ((id->rid & PCI_NO_MSI) == 0 && pci_msi_count(dev) == 1) { count = 1; if (pci_alloc_msi(dev, &count) == 0) { sc->sc_irid = 1; diff --git a/sys/dev/uart/uart_bus_puc.c b/sys/dev/uart/uart_bus_puc.c index 5f6c5cdbbdad..661db8595262 100644 --- a/sys/dev/uart/uart_bus_puc.c +++ b/sys/dev/uart/uart_bus_puc.c @@ -52,7 +52,7 @@ static device_method_t uart_puc_methods[] = { /* Serdev interface */ DEVMETHOD(serdev_ihand, uart_bus_ihand), DEVMETHOD(serdev_ipend, uart_bus_ipend), - { 0, 0 } + DEVMETHOD_END }; static driver_t uart_puc_driver = { diff --git a/sys/dev/uart/uart_bus_scc.c b/sys/dev/uart/uart_bus_scc.c index 731c1532851a..ad826dfe80d4 100644 --- a/sys/dev/uart/uart_bus_scc.c +++ b/sys/dev/uart/uart_bus_scc.c @@ -53,7 +53,7 @@ static device_method_t uart_scc_methods[] = { /* Serdev interface */ DEVMETHOD(serdev_ihand, uart_bus_ihand), DEVMETHOD(serdev_sysdev, uart_bus_sysdev), - { 0, 0 } + DEVMETHOD_END }; static driver_t uart_scc_driver = { diff --git a/sys/dev/uart/uart_dev_imx.c b/sys/dev/uart/uart_dev_imx.c index b40012a313ca..021475ecc676 100644 --- a/sys/dev/uart/uart_dev_imx.c +++ b/sys/dev/uart/uart_dev_imx.c @@ -296,7 +296,7 @@ static kobj_method_t imx_uart_methods[] = { KOBJMETHOD(uart_transmit, imx_uart_bus_transmit), KOBJMETHOD(uart_grab, imx_uart_bus_grab), KOBJMETHOD(uart_ungrab, imx_uart_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; static struct uart_class uart_imx_class = { diff --git a/sys/dev/uart/uart_dev_lowrisc.c b/sys/dev/uart/uart_dev_lowrisc.c index 19630deb4b78..ef70118a817a 100644 --- a/sys/dev/uart/uart_dev_lowrisc.c +++ b/sys/dev/uart/uart_dev_lowrisc.c @@ -168,7 +168,7 @@ static kobj_method_t lowrisc_uart_methods[] = { KOBJMETHOD(uart_transmit, lowrisc_uart_bus_transmit), KOBJMETHOD(uart_grab, lowrisc_uart_bus_grab), KOBJMETHOD(uart_ungrab, lowrisc_uart_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; static struct uart_class uart_lowrisc_class = { diff --git a/sys/dev/uart/uart_dev_mu.c b/sys/dev/uart/uart_dev_mu.c index ddaca2edce2c..abfb105f6c9c 100644 --- a/sys/dev/uart/uart_dev_mu.c +++ b/sys/dev/uart/uart_dev_mu.c @@ -280,7 +280,7 @@ static kobj_method_t uart_mu_methods[] = { KOBJMETHOD(uart_transmit, uart_mu_bus_transmit), KOBJMETHOD(uart_grab, uart_mu_bus_grab), KOBJMETHOD(uart_ungrab, uart_mu_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; static struct uart_class uart_mu_class = { diff --git a/sys/dev/uart/uart_dev_mvebu.c b/sys/dev/uart/uart_dev_mvebu.c index 8f989aa0ca14..a4d331bea6c0 100644 --- a/sys/dev/uart/uart_dev_mvebu.c +++ b/sys/dev/uart/uart_dev_mvebu.c @@ -299,7 +299,7 @@ static kobj_method_t uart_mvebu_methods[] = { KOBJMETHOD(uart_transmit, uart_mvebu_bus_transmit), KOBJMETHOD(uart_grab, uart_mvebu_bus_grab), KOBJMETHOD(uart_ungrab, uart_mvebu_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; struct uart_class uart_mvebu_class = { diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c index c38d50e54ad8..c13eabe9055e 100644 --- a/sys/dev/uart/uart_dev_ns8250.c +++ b/sys/dev/uart/uart_dev_ns8250.c @@ -89,9 +89,7 @@ SYSCTL_INT(_hw, OID_AUTO, uart_noise_threshold, CTLFLAG_RWTUN, * options EARLY_PRINTF=ns8250 */ #if CHECK_EARLY_PRINTF(ns8250) -#if !(defined(__amd64__) || defined(__i386__)) -#error ns8250 early putc is x86 specific as it uses inb/outb -#endif +#if (defined(__amd64__) || defined(__i386__)) static void uart_ns8250_early_putc(int c) { @@ -103,7 +101,45 @@ uart_ns8250_early_putc(int c) continue; outb(tx, c); } +#elif (defined(__arm__) || defined(__aarch64__)) +#ifndef UART_NS8250_EARLY_REG_IO_WIDTH +#error Option 'UART_NS8250_EARLY_REG_IO_WIDTH' is missing. +#endif +#ifndef UART_NS8250_EARLY_REG_SHIFT +#error Option 'UART_NS8250_EARLY_REG_SHIFT' is missing. +#endif + +#if UART_NS8250_EARLY_REG_IO_WIDTH == 1 +#define T uint8_t +#elif UART_NS8250_EARLY_REG_IO_WIDTH == 2 +#define T uint16_t +#elif UART_NS8250_EARLY_REG_IO_WIDTH == 4 +#define T uint32_t + +#else +#error Invalid/unsupported UART_NS8250_EARLY_REG_IO_WIDTH value +#endif + +#include <machine/machdep.h> + +static void +uart_ns8250_early_putc(int c) +{ + volatile T *stat; + volatile T *tx; + + stat = (T *)(socdev_va + (REG_LSR << UART_NS8250_EARLY_REG_SHIFT)); + tx = (T *)(socdev_va + (REG_DATA << UART_NS8250_EARLY_REG_SHIFT)); + + while ((*stat & LSR_THRE) == 0) + continue; + *tx = c & 0xff; +} +#else +#error ns8250 early putc is not implemented for current architecture +#endif early_putc_t *early_putc = uart_ns8250_early_putc; +#undef DTYPE #endif /* EARLY_PRINTF */ /* @@ -963,6 +999,15 @@ ns8250_bus_probe(struct uart_softc *sc) uart_setreg(bas, REG_IER, ier); uart_setreg(bas, REG_MCR, mcr); uart_setreg(bas, REG_FCR, 0); + /* + * The Alder Lake AMT SOL Redirection device will never + * set LSR_OE (when in loopback mode at least) and + * instead block further input by not setting LSR_TEMT. + * Recovering the device afterwards into a working + * state requires re-writing the LCR register. This + * should be harmless on all other devices. + */ + uart_setreg(bas, REG_LCR, uart_getreg(bas, REG_LCR)); uart_barrier(bas); count = 0; goto describe; diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c index 6afc693cd347..ae3c4d3218cf 100644 --- a/sys/dev/uart/uart_dev_pl011.c +++ b/sys/dev/uart/uart_dev_pl011.c @@ -367,7 +367,7 @@ static kobj_method_t uart_pl011_methods[] = { KOBJMETHOD(uart_transmit, uart_pl011_bus_transmit), KOBJMETHOD(uart_grab, uart_pl011_bus_grab), KOBJMETHOD(uart_ungrab, uart_pl011_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; static struct uart_class uart_pl011_class = { diff --git a/sys/dev/uart/uart_dev_quicc.c b/sys/dev/uart/uart_dev_quicc.c index d6a8846b874e..84d040f64942 100644 --- a/sys/dev/uart/uart_dev_quicc.c +++ b/sys/dev/uart/uart_dev_quicc.c @@ -261,7 +261,7 @@ static kobj_method_t quicc_methods[] = { KOBJMETHOD(uart_transmit, quicc_bus_transmit), KOBJMETHOD(uart_grab, quicc_bus_grab), KOBJMETHOD(uart_ungrab, quicc_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; struct uart_class uart_quicc_class = { diff --git a/sys/dev/uart/uart_dev_z8530.c b/sys/dev/uart/uart_dev_z8530.c index 45bf63f20bb2..56d9c96cd31a 100644 --- a/sys/dev/uart/uart_dev_z8530.c +++ b/sys/dev/uart/uart_dev_z8530.c @@ -297,7 +297,7 @@ static kobj_method_t z8530_methods[] = { KOBJMETHOD(uart_transmit, z8530_bus_transmit), KOBJMETHOD(uart_grab, z8530_bus_grab), KOBJMETHOD(uart_ungrab, z8530_bus_ungrab), - { 0, 0 } + KOBJMETHOD_END }; struct uart_class uart_z8530_class = { diff --git a/sys/dev/uart/uart_tty.c b/sys/dev/uart/uart_tty.c index d15d1d0c6ac2..7f0f730b3b6e 100644 --- a/sys/dev/uart/uart_tty.c +++ b/sys/dev/uart/uart_tty.c @@ -447,8 +447,9 @@ uart_tty_detach(struct uart_softc *sc) tp = sc->sc_u.u_tty.tp; - tty_lock(tp); swi_remove(sc->sc_softih); + + tty_lock(tp); tty_rel_gone(tp); return (0); diff --git a/sys/dev/ufshci/ufshci_acpi.c b/sys/dev/ufshci/ufshci_acpi.c new file mode 100644 index 000000000000..94da0d3cb411 --- /dev/null +++ b/sys/dev/ufshci/ufshci_acpi.c @@ -0,0 +1,248 @@ +/*- + * Copyright (c) 2026, Samsung Electronics Co., Ltd. + * Written by Jaeyoon Choi + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/bus.h> +#include <sys/conf.h> +#include <sys/proc.h> +#include <sys/smp.h> + +#include <vm/vm.h> + +#include <contrib/dev/acpica/include/acpi.h> + +#include <dev/acpica/acpivar.h> + +#include "ufshci_private.h" + +static int ufshci_acpi_probe(device_t); +static int ufshci_acpi_attach(device_t); +static int ufshci_acpi_detach(device_t); +static int ufshci_acpi_suspend(device_t); +static int ufshci_acpi_resume(device_t); + +static device_method_t ufshci_acpi_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ufshci_acpi_probe), + DEVMETHOD(device_attach, ufshci_acpi_attach), + DEVMETHOD(device_detach, ufshci_acpi_detach), + DEVMETHOD(device_suspend, ufshci_acpi_suspend), + DEVMETHOD(device_resume, ufshci_acpi_resume), { 0, 0 } +}; + +static driver_t ufshci_acpi_driver = { + "ufshci", + ufshci_acpi_methods, + sizeof(struct ufshci_controller), +}; + +DRIVER_MODULE(ufshci, acpi, ufshci_acpi_driver, 0, 0); +MODULE_DEPEND(ufshci, acpi, 1, 1, 1); + +static struct ufshci_acpi_device { + const char *hid; + const char *desc; + uint32_t ref_clk; + uint32_t quirks; +} ufshci_acpi_devices[] = { + { "QCOM24A5", "Qualcomm Snapdragon X Elite UFS Host Controller", + UFSHCI_REF_CLK_19_2MHz, + UFSHCI_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH | + UFSHCI_QUIRK_BROKEN_LSDBS_MCQS_CAP }, + { 0x00000000, NULL, 0, 0 } +}; + +static char *ufshci_acpi_ids[] = { "QCOM24A5", NULL }; + +static const struct ufshci_acpi_device * +ufshci_acpi_find_device(device_t dev) +{ + char *hid; + int i; + int rv; + + rv = ACPI_ID_PROBE(device_get_parent(dev), dev, ufshci_acpi_ids, &hid); + if (rv > 0) + return (NULL); + + for (i = 0; ufshci_acpi_devices[i].hid != NULL; i++) { + if (strcmp(ufshci_acpi_devices[i].hid, hid) != 0) + continue; + return (&ufshci_acpi_devices[i]); + } + + return (NULL); +} + +static int +ufshci_acpi_probe(device_t dev) +{ + struct ufshci_controller *ctrlr = device_get_softc(dev); + const struct ufshci_acpi_device *acpi_dev; + + acpi_dev = ufshci_acpi_find_device(dev); + if (acpi_dev == NULL) + return (ENXIO); + + if (acpi_dev->hid) { + ctrlr->quirks = acpi_dev->quirks; + ctrlr->ref_clk = acpi_dev->ref_clk; + } + + if (acpi_dev->desc) { + device_set_desc(dev, acpi_dev->desc); + return (BUS_PROBE_DEFAULT); + } + + return (ENXIO); +} + +static int +ufshci_acpi_allocate_memory(struct ufshci_controller *ctrlr) +{ + ctrlr->resource_id = 0; + ctrlr->resource = bus_alloc_resource_any(ctrlr->dev, SYS_RES_MEMORY, + &ctrlr->resource_id, RF_ACTIVE); + + if (ctrlr->resource == NULL) { + ufshci_printf(ctrlr, "unable to allocate acpi resource\n"); + return (ENOMEM); + } + + ctrlr->bus_tag = rman_get_bustag(ctrlr->resource); + ctrlr->bus_handle = rman_get_bushandle(ctrlr->resource); + ctrlr->regs = (struct ufshci_registers *)ctrlr->bus_handle; + + return (0); +} + +static int +ufshci_acpi_setup_shared(struct ufshci_controller *ctrlr) +{ + int error; + + ctrlr->num_io_queues = 1; + ctrlr->rid = 0; + ctrlr->res = bus_alloc_resource_any(ctrlr->dev, SYS_RES_IRQ, + &ctrlr->rid, RF_SHAREABLE | RF_ACTIVE); + if (ctrlr->res == NULL) { + ufshci_printf(ctrlr, "unable to allocate shared interrupt\n"); + return (ENOMEM); + } + + error = bus_setup_intr(ctrlr->dev, ctrlr->res, + INTR_TYPE_MISC | INTR_MPSAFE, NULL, ufshci_ctrlr_shared_handler, + ctrlr, &ctrlr->tag); + if (error) { + ufshci_printf(ctrlr, "unable to setup shared interrupt\n"); + return (error); + } + + return (0); +} + +static int +ufshci_acpi_setup_interrupts(struct ufshci_controller *ctrlr) +{ + int num_io_queues, per_cpu_io_queues, min_cpus_per_ioq; + + /* + * TODO: Need to implement MCQ(Multi Circular Queue) + * Example: num_io_queues = mp_ncpus; + */ + num_io_queues = 1; + TUNABLE_INT_FETCH("hw.ufshci.num_io_queues", &num_io_queues); + if (num_io_queues < 1 || num_io_queues > mp_ncpus) + num_io_queues = mp_ncpus; + + per_cpu_io_queues = 1; + TUNABLE_INT_FETCH("hw.ufshci.per_cpu_io_queues", &per_cpu_io_queues); + if (per_cpu_io_queues == 0) + num_io_queues = 1; + + min_cpus_per_ioq = smp_threads_per_core; + TUNABLE_INT_FETCH("hw.ufshci.min_cpus_per_ioq", &min_cpus_per_ioq); + if (min_cpus_per_ioq > 1) { + num_io_queues = min(num_io_queues, + max(1, mp_ncpus / min_cpus_per_ioq)); + } + + if (num_io_queues > vm_ndomains) + num_io_queues -= num_io_queues % vm_ndomains; + + ctrlr->num_io_queues = num_io_queues; + return (ufshci_acpi_setup_shared(ctrlr)); +} + +static int +ufshci_acpi_attach(device_t dev) +{ + struct ufshci_controller *ctrlr = device_get_softc(dev); + int status; + + ctrlr->dev = dev; + status = ufshci_acpi_allocate_memory(ctrlr); + if (status != 0) + goto bad; + + status = ufshci_acpi_setup_interrupts(ctrlr); + if (status != 0) + goto bad; + + return (ufshci_attach(dev)); +bad: + if (ctrlr->resource != NULL) { + bus_release_resource(dev, SYS_RES_MEMORY, ctrlr->resource_id, + ctrlr->resource); + } + + if (ctrlr->tag) + bus_teardown_intr(dev, ctrlr->res, ctrlr->tag); + + if (ctrlr->res) + bus_release_resource(dev, SYS_RES_IRQ, rman_get_rid(ctrlr->res), + ctrlr->res); + + return (status); +} + +static int +ufshci_acpi_detach(device_t dev) +{ + return (ufshci_detach(dev)); +} + +static int +ufshci_acpi_suspend(device_t dev) +{ + struct ufshci_controller *ctrlr = device_get_softc(dev); + int error; + + error = bus_generic_suspend(dev); + if (error) + return (error); + + /* Currently, PCI-based ufshci only supports POWER_STYPE_STANDBY */ + error = ufshci_ctrlr_suspend(ctrlr, POWER_STYPE_STANDBY); + return (error); +} + +static int +ufshci_acpi_resume(device_t dev) +{ + struct ufshci_controller *ctrlr = device_get_softc(dev); + int error; + + error = ufshci_ctrlr_resume(ctrlr, POWER_STYPE_AWAKE); + if (error) + return (error); + + error = bus_generic_resume(dev); + return (error); +} diff --git a/sys/dev/ufshci/ufshci_ctrlr.c b/sys/dev/ufshci/ufshci_ctrlr.c index f011d03189e0..244aa723d02a 100644 --- a/sys/dev/ufshci/ufshci_ctrlr.c +++ b/sys/dev/ufshci/ufshci_ctrlr.c @@ -21,6 +21,50 @@ ufshci_ctrlr_fail(struct ufshci_controller *ctrlr) ufshci_req_queue_fail(ctrlr, &ctrlr->transfer_req_queue); } +/* Some controllers require a reinit after switching to the max gear. */ +static int +ufshci_ctrlr_reinit_after_max_gear_switch(struct ufshci_controller *ctrlr) +{ + int error; + + /* Reset device */ + ufshci_utmr_req_queue_disable(ctrlr); + ufshci_utr_req_queue_disable(ctrlr); + + error = ufshci_ctrlr_disable(ctrlr); + if (error != 0) + return (error); + + error = ufshci_ctrlr_enable(ctrlr); + if (error != 0) + return (error); + + error = ufshci_utmr_req_queue_enable(ctrlr); + if (error != 0) + return (error); + + error = ufshci_utr_req_queue_enable(ctrlr); + if (error != 0) + return (error); + + error = ufshci_ctrlr_send_nop(ctrlr); + if (error != 0) + return (error); + + /* Reinit the target device. */ + error = ufshci_dev_init(ctrlr); + if (error != 0) + return (error); + + /* Initialize Reference Clock */ + error = ufshci_dev_init_reference_clock(ctrlr); + if (error != 0) + return (error); + + /* Initialize unipro */ + return (ufshci_dev_init_unipro(ctrlr)); +} + static void ufshci_ctrlr_start(struct ufshci_controller *ctrlr, bool resetting) { @@ -77,6 +121,12 @@ ufshci_ctrlr_start(struct ufshci_controller *ctrlr, bool resetting) ufshci_dev_init_uic_link_state(ctrlr); + if ((ctrlr->quirks & UFSHCI_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH) && + ufshci_ctrlr_reinit_after_max_gear_switch(ctrlr) != 0) { + ufshci_ctrlr_fail(ctrlr); + return; + } + /* Read Controller Descriptor (Device, Geometry) */ if (ufshci_dev_get_descriptor(ctrlr) != 0) { ufshci_ctrlr_fail(ctrlr); @@ -199,7 +249,7 @@ ufshci_ctrlr_disable(struct ufshci_controller *ctrlr) return (error); } -static int +int ufshci_ctrlr_enable(struct ufshci_controller *ctrlr) { uint32_t ie, hcs; @@ -302,15 +352,18 @@ ufshci_ctrlr_construct(struct ufshci_controller *ctrlr, device_t dev) /* Read Device Capabilities */ ctrlr->cap = cap = ufshci_mmio_read_4(ctrlr, cap); - ctrlr->is_single_db_supported = UFSHCIV(UFSHCI_CAP_REG_LSDBS, cap); - /* - * TODO: This driver does not yet support multi-queue. - * Check the UFSHCI_CAP_REG_MCQS bit in the future to determine if - * multi-queue support is available. - */ - ctrlr->is_mcq_supported = false; - if (!(ctrlr->is_single_db_supported == 0 || ctrlr->is_mcq_supported)) + if (ctrlr->quirks & UFSHCI_QUIRK_BROKEN_LSDBS_MCQS_CAP) { + ctrlr->is_single_db_supported = true; + ctrlr->is_mcq_supported = true; + } else { + ctrlr->is_single_db_supported = (UFSHCIV(UFSHCI_CAP_REG_LSDBS, + cap) == 0); + ctrlr->is_mcq_supported = (UFSHCIV(UFSHCI_CAP_REG_MCQS, cap) == + 1); + } + if (!(ctrlr->is_single_db_supported || ctrlr->is_mcq_supported)) return (ENXIO); + /* * The maximum transfer size supported by UFSHCI spec is 65535 * 256 KiB * However, we limit the maximum transfer size to 1MiB(256 * 4KiB) for diff --git a/sys/dev/ufshci/ufshci_dev.c b/sys/dev/ufshci/ufshci_dev.c index 406130c537a7..0fedbca9a90e 100644 --- a/sys/dev/ufshci/ufshci_dev.c +++ b/sys/dev/ufshci/ufshci_dev.c @@ -273,40 +273,31 @@ ufshci_dev_init_unipro(struct ufshci_controller *ctrlr) uint32_t pa_granularity, peer_pa_granularity; uint32_t t_activate, pear_t_activate; - /* - * Unipro Version: - * - 7~15 = Above 2.0, 6 = 2.0, 5 = 1.8, 4 = 1.61, 3 = 1.6, 2 = 1.41, - * 1 = 1.40, 0 = Reserved - */ - if (ufshci_uic_send_dme_get(ctrlr, PA_LocalVerInfo, - &ctrlr->unipro_version)) - return (ENXIO); - if (ufshci_uic_send_dme_get(ctrlr, PA_RemoteVerInfo, - &ctrlr->ufs_dev.unipro_version)) - return (ENXIO); - - /* - * PA_Granularity: Granularity for PA_TActivate and PA_Hibern8Time - * - 1=1us, 2=4us, 3=8us, 4=16us, 5=32us, 6=100us - */ - if (ufshci_uic_send_dme_get(ctrlr, PA_Granularity, &pa_granularity)) - return (ENXIO); - if (ufshci_uic_send_dme_peer_get(ctrlr, PA_Granularity, - &peer_pa_granularity)) - return (ENXIO); + if (ctrlr->quirks & UFSHCI_QUIRK_LONG_PEER_PA_TACTIVATE) { + /* + * PA_Granularity: Granularity for PA_TActivate and + * PA_Hibern8Time + * - 1=1us, 2=4us, 3=8us, 4=16us, 5=32us, 6=100us + */ + if (ufshci_uic_send_dme_get(ctrlr, PA_Granularity, + &pa_granularity)) + return (ENXIO); + if (ufshci_uic_send_dme_peer_get(ctrlr, PA_Granularity, + &peer_pa_granularity)) + return (ENXIO); - /* - * PA_TActivate: Time to wait before activating a burst in order to - * wake-up peer M-RX - * UniPro automatically sets timing information such as PA_TActivate - * through the PACP_CAP_EXT1_ind command during Link Startup operation. - */ - if (ufshci_uic_send_dme_get(ctrlr, PA_TActivate, &t_activate)) - return (ENXIO); - if (ufshci_uic_send_dme_peer_get(ctrlr, PA_TActivate, &pear_t_activate)) - return (ENXIO); + /* + * PA_TActivate: Time to wait before activating a burst in order + * to wake-up peer M-RX UniPro automatically sets timing + * information such as PA_TActivate through the + * PACP_CAP_EXT1_ind command during Link Startup operation. + */ + if (ufshci_uic_send_dme_get(ctrlr, PA_TActivate, &t_activate)) + return (ENXIO); + if (ufshci_uic_send_dme_peer_get(ctrlr, PA_TActivate, + &pear_t_activate)) + return (ENXIO); - if (ctrlr->quirks & UFSHCI_QUIRK_LONG_PEER_PA_TACTIVATE) { /* * Intel Lake-field UFSHCI has a quirk. We need to add 200us to * the PEER's PA_TActivate. @@ -334,7 +325,7 @@ ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr) */ const uint32_t fast_mode = 1; const uint32_t rx_bit_shift = 4; - uint32_t power_mode, peer_granularity; + uint32_t peer_granularity; /* Update lanes with available TX/RX lanes */ if (ufshci_uic_send_dme_get(ctrlr, PA_AvailTxDataLanes, @@ -361,9 +352,11 @@ ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr) if (ctrlr->quirks & UFSHCI_QUIRK_CHANGE_LANE_AND_GEAR_SEPARATELY) { /* Before changing gears, first change the number of lanes. */ - if (ufshci_uic_send_dme_get(ctrlr, PA_PWRMode, &power_mode)) + if (ufshci_uic_send_dme_get(ctrlr, PA_PWRMode, + &ctrlr->tx_rx_power_mode)) return (ENXIO); - if (ufshci_uic_send_dme_set(ctrlr, PA_PWRMode, power_mode)) + if (ufshci_uic_send_dme_set(ctrlr, PA_PWRMode, + ctrlr->tx_rx_power_mode)) return (ENXIO); /* Wait for power mode changed. */ @@ -424,8 +417,8 @@ ufshci_dev_init_uic_power_mode(struct ufshci_controller *ctrlr) return (ENXIO); /* Set TX/RX PWRMode */ - power_mode = (fast_mode << rx_bit_shift) | fast_mode; - if (ufshci_uic_send_dme_set(ctrlr, PA_PWRMode, power_mode)) + ctrlr->tx_rx_power_mode = (fast_mode << rx_bit_shift) | fast_mode; + if (ufshci_uic_send_dme_set(ctrlr, PA_PWRMode, ctrlr->tx_rx_power_mode)) return (ENXIO); /* Wait for power mode changed. */ diff --git a/sys/dev/ufshci/ufshci_pci.c b/sys/dev/ufshci/ufshci_pci.c index 6a4182a55a7d..b6b8124bc3a6 100644 --- a/sys/dev/ufshci/ufshci_pci.c +++ b/sys/dev/ufshci/ufshci_pci.c @@ -34,7 +34,7 @@ static device_method_t ufshci_pci_methods[] = { DEVMETHOD(device_attach, ufshci_pci_attach), DEVMETHOD(device_detach, ufshci_pci_detach), DEVMETHOD(device_suspend, ufshci_pci_suspend), - DEVMETHOD(device_resume, ufshci_pci_resume), { 0, 0 } + DEVMETHOD(device_resume, ufshci_pci_resume), DEVMETHOD_END }; static driver_t ufshci_pci_driver = { diff --git a/sys/dev/ufshci/ufshci_private.h b/sys/dev/ufshci/ufshci_private.h index b57142bf58fc..067b51a419e8 100644 --- a/sys/dev/ufshci/ufshci_private.h +++ b/sys/dev/ufshci/ufshci_private.h @@ -278,8 +278,6 @@ struct ufshci_device { struct ufshci_device_descriptor dev_desc; struct ufshci_geometry_descriptor geo_desc; - uint32_t unipro_version; - /* WriteBooster */ bool is_wb_enabled; bool is_wb_flush_enabled; @@ -317,10 +315,15 @@ struct ufshci_controller { #define UFSHCI_QUIRK_NOT_SUPPORT_ABORT_TASK \ 16 /* QEMU does not support Task Management Request */ #define UFSHCI_QUIRK_SKIP_WELL_KNOWN_LUNS \ - 32 /* QEMU does not support Well known logical units*/ + 32 /* QEMU does not support Well known logical units */ #define UFSHCI_QUIRK_BROKEN_AUTO_HIBERNATE \ 64 /* Some controllers have the Auto hibernate feature enabled but it \ does not work. */ +#define UFSHCI_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH \ + 128 /* Some controllers need to reinit the device after gear switch. \ + */ +#define UFSHCI_QUIRK_BROKEN_LSDBS_MCQS_CAP \ + 256 /* Some controllers have their LSDB and MCQS fields reset to 0. */ uint32_t ref_clk; @@ -393,13 +396,13 @@ struct ufshci_controller { /* UFS Transport Protocol Layer (UTP) */ struct ufshci_req_queue task_mgmt_req_queue; struct ufshci_req_queue transfer_req_queue; - bool is_single_db_supported; /* 0 = supported */ - bool is_mcq_supported; /* 1 = supported */ + bool is_single_db_supported; + bool is_mcq_supported; /* UFS Interconnect Layer (UIC) */ struct mtx uic_cmd_lock; - uint32_t unipro_version; - uint8_t hs_gear; + uint32_t tx_rx_power_mode; + uint32_t hs_gear; uint32_t tx_lanes; uint32_t rx_lanes; uint32_t max_rx_hs_gear; @@ -445,6 +448,7 @@ int ufshci_ctrlr_suspend(struct ufshci_controller *ctrlr, int ufshci_ctrlr_resume(struct ufshci_controller *ctrlr, enum power_stype stype); int ufshci_ctrlr_disable(struct ufshci_controller *ctrlr); +int ufshci_ctrlr_enable(struct ufshci_controller *ctrlr); /* ctrlr defined as void * to allow use with config_intrhook. */ void ufshci_ctrlr_start_config_hook(void *arg); void ufshci_ctrlr_poll(struct ufshci_controller *ctrlr); diff --git a/sys/dev/ufshci/ufshci_req_sdb.c b/sys/dev/ufshci/ufshci_req_sdb.c index ca47aa159c5b..54542f48b32c 100644 --- a/sys/dev/ufshci/ufshci_req_sdb.c +++ b/sys/dev/ufshci/ufshci_req_sdb.c @@ -374,34 +374,63 @@ ufshci_req_sdb_enable(struct ufshci_controller *ctrlr, struct ufshci_req_queue *req_queue) { struct ufshci_hw_queue *hwq = &req_queue->hwq[UFSHCI_SDB_Q]; + int error = 0; + + mtx_lock(&hwq->recovery_lock); + mtx_lock(&hwq->qlock); if (req_queue->is_task_mgmt) { uint32_t hcs, utmrldbr, utmrlrsr; + uint32_t utmrlba, utmrlbau; + + /* + * Some controllers require re-enabling. When a controller is + * re-enabled, the utmrlba registers are initialized, and these + * must be reconfigured upon re-enabling. + */ + utmrlba = hwq->req_queue_addr & 0xffffffff; + utmrlbau = hwq->req_queue_addr >> 32; + ufshci_mmio_write_4(ctrlr, utmrlba, utmrlba); + ufshci_mmio_write_4(ctrlr, utmrlbau, utmrlbau); hcs = ufshci_mmio_read_4(ctrlr, hcs); if (!(hcs & UFSHCIM(UFSHCI_HCS_REG_UTMRLRDY))) { ufshci_printf(ctrlr, "UTP task management request list is not ready\n"); - return (ENXIO); + error = ENXIO; + goto out; } utmrldbr = ufshci_mmio_read_4(ctrlr, utmrldbr); if (utmrldbr != 0) { ufshci_printf(ctrlr, "UTP task management request list door bell is not ready\n"); - return (ENXIO); + error = ENXIO; + goto out; } utmrlrsr = UFSHCIM(UFSHCI_UTMRLRSR_REG_UTMRLRSR); ufshci_mmio_write_4(ctrlr, utmrlrsr, utmrlrsr); } else { uint32_t hcs, utrldbr, utrlcnr, utrlrsr; + uint32_t utrlba, utrlbau; + + /* + * Some controllers require re-enabling. When a controller is + * re-enabled, the utrlba registers are initialized, and these + * must be reconfigured upon re-enabling. + */ + utrlba = hwq->req_queue_addr & 0xffffffff; + utrlbau = hwq->req_queue_addr >> 32; + ufshci_mmio_write_4(ctrlr, utrlba, utrlba); + ufshci_mmio_write_4(ctrlr, utrlbau, utrlbau); hcs = ufshci_mmio_read_4(ctrlr, hcs); if (!(hcs & UFSHCIM(UFSHCI_HCS_REG_UTRLRDY))) { ufshci_printf(ctrlr, "UTP transfer request list is not ready\n"); - return (ENXIO); + error = ENXIO; + goto out; } utrldbr = ufshci_mmio_read_4(ctrlr, utrldbr); @@ -434,7 +463,10 @@ ufshci_req_sdb_enable(struct ufshci_controller *ctrlr, hwq->recovery_state = RECOVERY_NONE; - return (0); +out: + mtx_unlock(&hwq->qlock); + mtx_unlock(&hwq->recovery_lock); + return (error); } int diff --git a/sys/dev/ufshci/ufshci_sim.c b/sys/dev/ufshci/ufshci_sim.c index bee1fff858ff..404f3e99d1e2 100644 --- a/sys/dev/ufshci/ufshci_sim.c +++ b/sys/dev/ufshci/ufshci_sim.c @@ -494,7 +494,7 @@ ufshci_sim_send_ssu(struct ufshci_controller *ctrlr, bool start, return ENOMEM; } - scsi_start_stop(&ccb->csio, + scsi_start_stop_pc(&ccb->csio, /*retries*/ 4, /*cbfcnp*/ NULL, /*tag_action*/ MSG_SIMPLE_Q_TAG, diff --git a/sys/dev/ufshci/ufshci_sysctl.c b/sys/dev/ufshci/ufshci_sysctl.c index 495f087f3c50..a113e951798e 100644 --- a/sys/dev/ufshci/ufshci_sysctl.c +++ b/sys/dev/ufshci/ufshci_sysctl.c @@ -193,7 +193,7 @@ ufshci_sysctl_initialize_ctrlr(struct ufshci_controller *ctrlr) CTLFLAG_RD, &ctrlr->num_io_queues, 0, "Number of I/O queue pairs"); SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "cap", CTLFLAG_RD, - &ctrlr->cap, 0, "Number of I/O queue pairs"); + &ctrlr->cap, 0, "Host controller capabilities register value"); SYSCTL_ADD_BOOL(ctrlr_ctx, ctrlr_list, OID_AUTO, "wb_enabled", CTLFLAG_RD, &dev->is_wb_enabled, 0, "WriteBooster enable/disable"); @@ -214,10 +214,6 @@ ufshci_sysctl_initialize_ctrlr(struct ufshci_controller *ctrlr) &dev->wb_user_space_config_option, 0, "WriteBooster preserve user space mode"); - SYSCTL_ADD_BOOL(ctrlr_ctx, ctrlr_list, OID_AUTO, "power_mode_supported", - CTLFLAG_RD, &dev->power_mode_supported, 0, - "Device power mode support"); - SYSCTL_ADD_BOOL(ctrlr_ctx, ctrlr_list, OID_AUTO, "auto_hibernation_supported", CTLFLAG_RD, &dev->auto_hibernation_supported, 0, @@ -229,9 +225,38 @@ ufshci_sysctl_initialize_ctrlr(struct ufshci_controller *ctrlr) ufshci_sysctl_ahit, "IU", "Auto-Hibernate Idle Timer Value (in microseconds)"); + SYSCTL_ADD_BOOL(ctrlr_ctx, ctrlr_list, OID_AUTO, "power_mode_supported", + CTLFLAG_RD, &dev->power_mode_supported, 0, + "Device power mode support"); + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "power_mode", CTLFLAG_RD, &dev->power_mode, 0, "Current device power mode"); + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "tx_rx_power_mode", + CTLFLAG_RD, &ctrlr->tx_rx_power_mode, 0, + "Current TX/RX PA_PWRMode value"); + + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "max_tx_lanes", + CTLFLAG_RD, &ctrlr->max_tx_lanes, 0, + "Maximum available TX data lanes"); + + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "max_rx_lanes", + CTLFLAG_RD, &ctrlr->max_rx_lanes, 0, + "Maximum available RX data lanes"); + + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "tx_lanes", CTLFLAG_RD, + &ctrlr->tx_lanes, 0, "Active TX data lanes"); + + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "rx_lanes", CTLFLAG_RD, + &ctrlr->rx_lanes, 0, "Active RX data lanes"); + + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "max_rx_hs_gear", + CTLFLAG_RD, &ctrlr->max_rx_hs_gear, 0, + "Maximum available RX HS gear"); + + SYSCTL_ADD_UINT(ctrlr_ctx, ctrlr_list, OID_AUTO, "hs_gear", CTLFLAG_RD, + &ctrlr->hs_gear, 0, "Active HS gear"); + SYSCTL_ADD_PROC(ctrlr_ctx, ctrlr_list, OID_AUTO, "timeout_period", CTLTYPE_UINT | CTLFLAG_RW | CTLFLAG_MPSAFE, &ctrlr->timeout_period, 0, ufshci_sysctl_timeout_period, "IU", diff --git a/sys/dev/usb/controller/ehci_fsl.c b/sys/dev/usb/controller/ehci_fsl.c index ce1749775ab2..a359908fd5f4 100644 --- a/sys/dev/usb/controller/ehci_fsl.c +++ b/sys/dev/usb/controller/ehci_fsl.c @@ -80,7 +80,7 @@ static device_method_t ehci_methods[] = { /* Bus interface */ DEVMETHOD(bus_print_child, bus_generic_print_child), - { 0, 0 } + DEVMETHOD_END }; /* kobj_class definition */ diff --git a/sys/dev/usb/input/uep.c b/sys/dev/usb/input/uep.c index 25eeb450491d..d54efe9cea2c 100644 --- a/sys/dev/usb/input/uep.c +++ b/sys/dev/usb/input/uep.c @@ -517,9 +517,9 @@ uep_close(struct usb_fifo *fifo, int fflags) static device_method_t uep_methods[] = { DEVMETHOD(device_probe, uep_probe), - DEVMETHOD(device_attach, uep_attach), + DEVMETHOD(device_attach, uep_attach), DEVMETHOD(device_detach, uep_detach), - { 0, 0 }, + DEVMETHOD_END }; static driver_t uep_driver = { diff --git a/sys/dev/usb/input/ukbd.c b/sys/dev/usb/input/ukbd.c index 57e9beac34b6..104e51c082c3 100644 --- a/sys/dev/usb/input/ukbd.c +++ b/sys/dev/usb/input/ukbd.c @@ -95,18 +95,29 @@ #ifdef USB_DEBUG static int ukbd_debug = 0; +#endif static int ukbd_no_leds = 0; static int ukbd_pollrate = 0; +static int ukbd_apple_fn_mode = 0; +static int ukbd_apple_swap_cmd_ctl = 0; +static int ukbd_apple_swap_cmd_opt = 0; static SYSCTL_NODE(_hw_usb, OID_AUTO, ukbd, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "USB keyboard"); +#ifdef USB_DEBUG SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, debug, CTLFLAG_RWTUN, &ukbd_debug, 0, "Debug level"); +#endif SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, no_leds, CTLFLAG_RWTUN, &ukbd_no_leds, 0, "Disables setting of keyboard leds"); SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, pollrate, CTLFLAG_RWTUN, &ukbd_pollrate, 0, "Force this polling rate, 1-1000Hz"); -#endif +SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, apple_fn_mode, CTLFLAG_RWTUN, + &ukbd_apple_fn_mode, 0, "0 = Fn + F1..12 -> media, 1 = F1..F12 -> media"); +SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, apple_swap_cmd_ctl, CTLFLAG_RWTUN, + &ukbd_apple_swap_cmd_ctl, 0, "Swap Command & Control keys"); +SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, apple_swap_cmd_opt, CTLFLAG_RWTUN, + &ukbd_apple_swap_cmd_opt, 0, "Swap Command & Option keys"); #define UKBD_EMULATE_ATSCANCODE 1 #define UKBD_DRIVER_NAME "ukbd" @@ -123,6 +134,10 @@ SYSCTL_INT(_hw_usb_ukbd, OID_AUTO, pollrate, CTLFLAG_RWTUN, #define MOD_EJECT 0x01 #define MOD_FN 0x02 +/* check evdev_usb_scancodes[] for names */ +#define APPLE_FN_KEY 0xff +#define APPLE_EJECT_KEY 0xec + struct ukbd_data { uint64_t bitmap[howmany(UKBD_NKEYCODE, 64)]; }; @@ -198,6 +213,7 @@ struct ukbd_softc { uint16_t sc_inputs; uint16_t sc_inputhead; uint16_t sc_inputtail; + uint16_t sc_vendor_id; uint8_t sc_leds; /* store for async led requests */ uint8_t sc_iface_index; @@ -282,9 +298,9 @@ static const uint8_t ukbd_trtab[256] = { NN, NN, NN, NN, NN, NN, NN, NN, /* D0 - D7 */ NN, NN, NN, NN, NN, NN, NN, NN, /* D8 - DF */ 29, 42, 56, 105, 90, 54, 93, 106, /* E0 - E7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* E8 - EF */ + NN, NN, NN, NN, 254, NN, NN, NN, /* E8 - EF */ NN, NN, NN, NN, NN, NN, NN, NN, /* F0 - F7 */ - NN, NN, NN, NN, NN, NN, NN, NN, /* F8 - FF */ + NN, NN, NN, NN, NN, NN, NN, 255, /* F8 - FF */ }; static const uint8_t ukbd_boot_desc[] = { @@ -582,14 +598,14 @@ ukbd_interrupt(struct ukbd_softc *sc) sc->sc_repeat_key = 0; } else { ukbd_put_key(sc, key | KEY_PRESS); - - sc->sc_co_basetime = sbinuptime(); - sc->sc_delay = sc->sc_kbd.kb_delay1; - ukbd_start_timer(sc); - - /* set repeat time for last key */ - sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1; - sc->sc_repeat_key = key; + if (key != APPLE_FN_KEY) { + sc->sc_co_basetime = sbinuptime(); + sc->sc_delay = sc->sc_kbd.kb_delay1; + ukbd_start_timer(sc); + /* set repeat time for last key */ + sc->sc_repeat_time = now + sc->sc_kbd.kb_delay1; + sc->sc_repeat_key = key; + } } } } @@ -669,6 +685,16 @@ static uint32_t ukbd_apple_fn(uint32_t keycode) { switch (keycode) { + case 0x0b: return 0x50; /* H -> LEFT ARROW */ + case 0x0d: return 0x51; /* J -> DOWN ARROW */ + case 0x0e: return 0x52; /* K -> UP ARROW */ + case 0x0f: return 0x4f; /* L -> RIGHT ARROW */ + case 0x36: return 0x4a; /* COMMA -> HOME */ + case 0x37: return 0x4d; /* DOT -> END */ + case 0x18: return 0x4b; /* U -> PGUP */ + case 0x07: return 0x4e; /* D -> PGDN */ + case 0x16: return 0x47; /* S -> SCROLLLOCK */ + case 0x13: return 0x46; /* P -> SYSRQ/PRTSC */ case 0x28: return 0x49; /* RETURN -> INSERT */ case 0x2a: return 0x4c; /* BACKSPACE -> DEL */ case 0x50: return 0x4a; /* LEFT ARROW -> HOME */ @@ -679,6 +705,51 @@ ukbd_apple_fn(uint32_t keycode) } } +/* separate so the sysctl doesn't butcher non-fn keys */ +static uint32_t +ukbd_apple_fn_media(uint32_t keycode) +{ + switch (keycode) { + case 0x3a: return 0xc0; /* F1 -> BRIGHTNESS DOWN */ + case 0x3b: return 0xc1; /* F2 -> BRIGHTNESS UP */ + case 0x3c: return 0xc2; /* F3 -> SCALE (MISSION CTRL)*/ + case 0x3d: return 0xc3; /* F4 -> DASHBOARD (LAUNCHPAD) */ + case 0x3e: return 0xc4; /* F5 -> KBD BACKLIGHT DOWN */ + case 0x3f: return 0xc5; /* F6 -> KBD BACKLIGHT UP */ + case 0x40: return 0xea; /* F7 -> MEDIA PREV */ + case 0x41: return 0xe8; /* F8 -> PLAY/PAUSE */ + case 0x42: return 0xeb; /* F9 -> MEDIA NEXT */ + case 0x43: return 0xef; /* F10 -> MUTE */ + case 0x44: return 0xee; /* F11 -> VOLUME DOWN */ + case 0x45: return 0xed; /* F12 -> VOLUME UP */ + default: return keycode; + } +} + +static uint32_t +ukbd_apple_doswap_cmd_ctl(uint32_t keycode) +{ + switch (keycode) { + case 0xe3: return 0xe0; /* LCMD -> LCTL */ + case 0xe7: return 0xe4; /* RCMD -> RCTL */ + case 0xe0: return 0xe3; /* LCTL -> LCMD */ + case 0xe4: return 0xe7; /* RCTL -> RCMD */ + default: return keycode; + } +} + +static uint32_t +ukbd_apple_doswap_cmd_opt(uint32_t keycode) +{ + switch (keycode) { + case 0xe3: return 0xe2; /* LCMD -> ROPT */ + case 0xe7: return 0xe6; /* RCMD -> ROPT */ + case 0xe2: return 0xe3; /* LOPT -> LCMD */ + case 0xe6: return 0xe7; /* ROPT -> RCMD */ + default: return keycode; + } +} + static uint32_t ukbd_apple_swap(uint32_t keycode) { @@ -740,18 +811,34 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) /* clear modifiers */ modifiers = 0; - /* scan through HID data */ + /* scan through HID data and expose magic apple keys */ if ((sc->sc_flags & UKBD_FLAG_APPLE_EJECT) && (id == sc->sc_id_apple_eject)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_eject)) + if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_eject)) { + sc->sc_ndata.bitmap[APPLE_EJECT_KEY / 64] |= + 1ULL << (APPLE_EJECT_KEY % 64); modifiers |= MOD_EJECT; + } else { + sc->sc_ndata.bitmap[APPLE_EJECT_KEY / 64] &= + ~(1ULL << (APPLE_EJECT_KEY % 64)); + } } if ((sc->sc_flags & UKBD_FLAG_APPLE_FN) && (id == sc->sc_id_apple_fn)) { - if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_fn)) + if (hid_get_data(sc->sc_buffer, len, &sc->sc_loc_apple_fn)) { + sc->sc_ndata.bitmap[APPLE_FN_KEY / 64] |= + 1ULL << (APPLE_FN_KEY % 64); modifiers |= MOD_FN; + } else { + sc->sc_ndata.bitmap[APPLE_FN_KEY / 64] &= + ~(1ULL << (APPLE_FN_KEY % 64)); + } } + int apply_apple_fn_media = (modifiers & MOD_FN) ? 1 : 0; + if (ukbd_apple_fn_mode) /* toggle from sysctl value */ + apply_apple_fn_media = !apply_apple_fn_media; + for (i = 0; i != UKBD_NKEYCODE; i++) { const uint64_t valid = sc->sc_loc_key_valid[i / 64]; const uint64_t mask = 1ULL << (i % 64); @@ -780,6 +867,12 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) } if (modifiers & MOD_FN) key = ukbd_apple_fn(key); + if (apply_apple_fn_media) + key = ukbd_apple_fn_media(key); + if (ukbd_apple_swap_cmd_ctl) + key = ukbd_apple_doswap_cmd_ctl(key); + if (ukbd_apple_swap_cmd_opt) + key = ukbd_apple_doswap_cmd_opt(key); if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) key = ukbd_apple_swap(key); if (key == KEY_NONE || key >= UKBD_NKEYCODE) @@ -792,6 +885,12 @@ ukbd_intr_callback(struct usb_xfer *xfer, usb_error_t error) if (modifiers & MOD_FN) key = ukbd_apple_fn(key); + if (apply_apple_fn_media) + key = ukbd_apple_fn_media(key); + if (ukbd_apple_swap_cmd_ctl) + key = ukbd_apple_doswap_cmd_ctl(key); + if (ukbd_apple_swap_cmd_opt) + key = ukbd_apple_doswap_cmd_opt(key); if (sc->sc_flags & UKBD_FLAG_APPLE_SWAP) key = ukbd_apple_swap(key); if (key == KEY_NONE || key == KEY_ERROR || key >= UKBD_NKEYCODE) @@ -1045,21 +1144,37 @@ ukbd_parse_hid(struct ukbd_softc *sc, const uint8_t *ptr, uint32_t len) hid_input, &sc->sc_kbd_id); /* investigate if this is an Apple Keyboard */ - if (hid_locate(ptr, len, - HID_USAGE2(HUP_CONSUMER, HUG_APPLE_EJECT), - hid_input, 0, &sc->sc_loc_apple_eject, &flags, - &sc->sc_id_apple_eject)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_APPLE_EJECT; - DPRINTFN(1, "Found Apple eject-key\n"); - } - if (hid_locate(ptr, len, - HID_USAGE2(0xFFFF, 0x0003), - hid_input, 0, &sc->sc_loc_apple_fn, &flags, - &sc->sc_id_apple_fn)) { - if (flags & HIO_VARIABLE) - sc->sc_flags |= UKBD_FLAG_APPLE_FN; - DPRINTFN(1, "Found Apple FN-key\n"); + if (sc->sc_vendor_id == USB_VENDOR_APPLE) { + if (hid_locate(ptr, len, + HID_USAGE2(HUP_CONSUMER, HUG_APPLE_EJECT), + hid_input, 0, &sc->sc_loc_apple_eject, &flags, + &sc->sc_id_apple_eject)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_APPLE_EJECT; + DPRINTFN(1, "Found Apple eject-key\n"); + } + /* + * check the same vendor pages that linux does to find the one + * apple uses for the function key. + */ + static const uint16_t apple_pages[] = { + HUP_APPLE, /* HID_UP_CUSTOM in linux */ + HUP_MICROSOFT, /* HID_UP_MSVENDOR in linux */ + HUP_HP, /* HID_UP_HPVENDOR2 in linux */ + 0xFFFF /* Original FreeBSD check (Remove?) */ + }; + for (int i = 0; i < (int)nitems(apple_pages); i++) { + if (hid_locate(ptr, len, + HID_USAGE2(apple_pages[i], 0x0003), + hid_input, 0, &sc->sc_loc_apple_fn, &flags, + &sc->sc_id_apple_fn)) { + if (flags & HIO_VARIABLE) + sc->sc_flags |= UKBD_FLAG_APPLE_FN; + DPRINTFN(1, "Found Apple FN-key on page 0x%04x\n", + apple_pages[i]); + break; + } + } } /* figure out event buffer */ @@ -1147,6 +1262,7 @@ ukbd_attach(device_t dev) sc->sc_udev = uaa->device; sc->sc_iface = uaa->iface; + sc->sc_vendor_id = uaa->info.idVendor; sc->sc_iface_index = uaa->info.bIfaceIndex; sc->sc_iface_no = uaa->info.bIfaceNum; sc->sc_mode = K_XLATE; diff --git a/sys/dev/usb/input/wsp.c b/sys/dev/usb/input/wsp.c index f78d64f69c08..2d7e3b796b17 100644 --- a/sys/dev/usb/input/wsp.c +++ b/sys/dev/usb/input/wsp.c @@ -231,6 +231,7 @@ enum tp_type { /* list of device capability bits */ #define HAS_INTEGRATED_BUTTON 1 +#define SUPPORTS_FORCETOUCH 2 /* trackpad finger data block size */ #define FSIZE_TYPE1 (14 * 2) @@ -285,7 +286,7 @@ struct wsp_tp { .delta = 0, }, [TYPE4] = { - .caps = HAS_INTEGRATED_BUTTON, + .caps = HAS_INTEGRATED_BUTTON | SUPPORTS_FORCETOUCH, .button = BUTTON_TYPE4, .offset = FINGER_TYPE4, .fsize = FSIZE_TYPE4, @@ -896,7 +897,8 @@ wsp_attach(device_t dev) WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->sc_params->x); WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->sc_params->y); /* finger pressure */ - WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p); + if ((sc->sc_params->tp->caps & SUPPORTS_FORCETOUCH) != 0) + WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->sc_params->p); /* finger major/minor axis */ WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->sc_params->w); WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->sc_params->w); @@ -1066,6 +1068,10 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) { evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt); evdev_sync(sc->sc_evdev); + if ((sc->sc_fflags & FREAD) == 0 || + usb_fifo_put_bytes_max( + sc->sc_fifo.fp[USB_FIFO_RX]) == 0) + goto tr_setup; } #endif sc->sc_status.flags &= ~MOUSE_POSCHANGED; @@ -1355,7 +1361,12 @@ wsp_intr_callback(struct usb_xfer *xfer, usb_error_t error) case USB_ST_SETUP: tr_setup: /* check if we can put more data into the FIFO */ - if (usb_fifo_put_bytes_max( + if ( +#ifdef EVDEV_SUPPORT + ((evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) != 0 && + (sc->sc_state & WSP_EVDEV_OPENED) != 0) || +#endif + usb_fifo_put_bytes_max( sc->sc_fifo.fp[USB_FIFO_RX]) != 0) { usbd_xfer_set_frame_len(xfer, 0, sc->tp_datalen); diff --git a/sys/dev/usb/net/if_smsc.c b/sys/dev/usb/net/if_smsc.c index 0ebbf8482446..8e16b8609144 100644 --- a/sys/dev/usb/net/if_smsc.c +++ b/sys/dev/usb/net/if_smsc.c @@ -1585,7 +1585,7 @@ smsc_bootargs_get_mac_addr(device_t dev, struct usb_ether *ue) node = OF_finddevice("/chosen"); if (node == -1) return (false); - if (OF_hasprop(node, "bootargs") == 0) { + if (!OF_hasprop(node, "bootargs")) { smsc_dbg_printf((struct smsc_softc *)ue->ue_sc, "bootargs not found"); return (false); diff --git a/sys/dev/usb/net/if_ure.c b/sys/dev/usb/net/if_ure.c index c3f7b622d687..7cf77466d420 100644 --- a/sys/dev/usb/net/if_ure.c +++ b/sys/dev/usb/net/if_ure.c @@ -24,6 +24,8 @@ * SUCH DAMAGE. */ +#include "opt_inet6.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/bus.h> @@ -44,6 +46,10 @@ /* needed for checksum offload */ #include <netinet/in.h> #include <netinet/ip.h> +#ifdef INET6 +#include <netinet/ip6.h> +#include <netinet6/ip6_var.h> +#endif #include <dev/mii/mii.h> #include <dev/mii/miivar.h> @@ -62,8 +68,6 @@ #include "miibus_if.h" -#include "opt_inet6.h" - #ifdef USB_DEBUG static int ure_debug = 0; @@ -96,21 +100,30 @@ static const STRUCT_USB_HOST_ID ure_devs[] = { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i), \ USB_IFACE_CLASS(UICLASS_VENDOR), \ USB_IFACE_SUBCLASS(UISUBCLASS_VENDOR) } + URE_DEV(CISCOLINKSYS, USB3GIGV1, 0), + URE_DEV(DLINK, DUBE1312, 0), URE_DEV(ELECOM, EDCQUA3C, 0), URE_DEV(LENOVO, RTL8153, URE_FLAG_8153), + URE_DEV(LENOVO, RTL8153_04, URE_FLAG_8153), + URE_DEV(LENOVO, TBT3LAN, 0), URE_DEV(LENOVO, TBT3LANGEN2, 0), URE_DEV(LENOVO, ONELINK, 0), - URE_DEV(LENOVO, RTL8153_04, URE_FLAG_8153), URE_DEV(LENOVO, ONELINKPLUS, URE_FLAG_8153), URE_DEV(LENOVO, USBCLAN, 0), URE_DEV(LENOVO, USBCLANGEN2, 0), URE_DEV(LENOVO, USBCLANHYBRID, 0), + URE_DEV(MICROSOFT, SURFETH1, 0), + URE_DEV(MICROSOFT, SURFETH2, 0), URE_DEV(MICROSOFT, WINDEVETH, 0), URE_DEV(NVIDIA, RTL8153, URE_FLAG_8153), + URE_DEV(REALTEK, RTL8050, URE_FLAG_8152), + URE_DEV(REALTEK, RTL8053, URE_FLAG_8153), URE_DEV(REALTEK, RTL8152, URE_FLAG_8152), URE_DEV(REALTEK, RTL8153, URE_FLAG_8153), - URE_DEV(TPLINK, RTL8153, URE_FLAG_8153), URE_DEV(REALTEK, RTL8156, URE_FLAG_8156), + URE_DEV(SAMSUNG, RTL8153, 0), + URE_DEV(TPLINK, RTL8153, URE_FLAG_8153), + URE_DEV(TPLINK, RTL8153_2, 0), #undef URE_DEV }; @@ -124,6 +137,7 @@ static usb_callback_t ure_bulk_write_callback; static miibus_readreg_t ure_miibus_readreg; static miibus_writereg_t ure_miibus_writereg; static miibus_statchg_t ure_miibus_statchg; +static miibus_linkchg_t ure_miibus_linkchg; static uether_fn_t ure_attach_post; static uether_fn_t ure_init; @@ -180,6 +194,7 @@ static device_method_t ure_methods[] = { DEVMETHOD(miibus_readreg, ure_miibus_readreg), DEVMETHOD(miibus_writereg, ure_miibus_writereg), DEVMETHOD(miibus_statchg, ure_miibus_statchg), + DEVMETHOD(miibus_linkchg, ure_miibus_linkchg), DEVMETHOD_END }; @@ -439,6 +454,8 @@ ure_miibus_statchg(device_t dev) struct mii_data *mii; if_t ifp; int locked; + uint16_t bmsr; + bool new_link, old_link; sc = device_get_softc(dev); mii = GET_MII(sc); @@ -451,6 +468,7 @@ ure_miibus_statchg(device_t dev) (if_getdrvflags(ifp) & IFF_DRV_RUNNING) == 0) goto done; + old_link = (sc->sc_flags & URE_FLAG_LINK) ? true : false; sc->sc_flags &= ~URE_FLAG_LINK; if ((mii->mii_media_status & (IFM_ACTIVE | IFM_AVALID)) == (IFM_ACTIVE | IFM_AVALID)) { @@ -471,14 +489,72 @@ ure_miibus_statchg(device_t dev) } } - /* Lost link, do nothing. */ - if ((sc->sc_flags & URE_FLAG_LINK) == 0) - goto done; + new_link = (sc->sc_flags & URE_FLAG_LINK) ? true : false; + if (old_link && !new_link) { + /* + * MII layer reports link down. Verify by reading + * the PHY BMSR register directly. BMSR link status + * is latched-low, so read twice: first clears any + * stale latch, second gives current state. + */ + (void)ure_ocp_reg_read(sc, + URE_OCP_BASE_MII + MII_BMSR * 2); + bmsr = ure_ocp_reg_read(sc, + URE_OCP_BASE_MII + MII_BMSR * 2); + + if (bmsr & BMSR_LINK) { + /* + * PHY still has link. This is a spurious + * link-down from the MII polling race (see + * PR 252165). Restore IFM_ACTIVE so the + * subsequent MIIBUS_LINKCHG check in + * mii_phy_update sees no change. + */ + device_printf(dev, + "spurious link down (PHY link up), overriding\n"); + sc->sc_flags |= URE_FLAG_LINK; + mii->mii_media_status |= IFM_ACTIVE; + } + } done: if (!locked) URE_UNLOCK(sc); } +static void +ure_miibus_linkchg(device_t dev) +{ + struct ure_softc *sc; + struct mii_data *mii; + int locked; + uint16_t bmsr; + + sc = device_get_softc(dev); + mii = GET_MII(sc); + locked = mtx_owned(&sc->sc_mtx); + if (locked == 0) + URE_LOCK(sc); + + /* + * This is called by the default miibus linkchg handler + * before it calls if_link_state_change(). If the PHY + * still has link but the MII layer lost IFM_ACTIVE due + * to the polling race (see PR 252165), restore it so the + * notification goes out as LINK_STATE_UP rather than DOWN. + */ + if (mii != NULL && (mii->mii_media_status & IFM_ACTIVE) == 0) { + (void)ure_ocp_reg_read(sc, + URE_OCP_BASE_MII + MII_BMSR * 2); + bmsr = ure_ocp_reg_read(sc, + URE_OCP_BASE_MII + MII_BMSR * 2); + if (bmsr & BMSR_LINK) + mii->mii_media_status |= IFM_ACTIVE; + } + + if (locked == 0) + URE_UNLOCK(sc); +} + /* * Probe for a RTL8152/RTL8153/RTL8156 chip. */ @@ -1015,6 +1091,7 @@ ure_attach_post_sub(struct usb_ether *ue) if_sethwassist(ifp, CSUM_IP|CSUM_IP_UDP|CSUM_IP_TCP); #ifdef INET6 if_setcapabilitiesbit(ifp, IFCAP_HWCSUM_IPV6, 0); + if_sethwassistbits(ifp, CSUM_IP6_UDP|CSUM_IP6_TCP, 0); #endif if_setcapenable(ifp, if_getcapabilities(ifp)); @@ -1463,6 +1540,7 @@ ure_ioctl(if_t ifp, u_long cmd, caddr_t data) if ((mask & IFCAP_TXCSUM) != 0 && (if_getcapabilities(ifp) & IFCAP_TXCSUM) != 0) { if_togglecapenable(ifp, IFCAP_TXCSUM); + if_togglehwassist(ifp, CSUM_IP|CSUM_IP_UDP|CSUM_IP_TCP); } if ((mask & IFCAP_RXCSUM) != 0 && (if_getcapabilities(ifp) & IFCAP_RXCSUM) != 0) { @@ -1471,6 +1549,7 @@ ure_ioctl(if_t ifp, u_long cmd, caddr_t data) if ((mask & IFCAP_TXCSUM_IPV6) != 0 && (if_getcapabilities(ifp) & IFCAP_TXCSUM_IPV6) != 0) { if_togglecapenable(ifp, IFCAP_TXCSUM_IPV6); + if_togglehwassist(ifp, CSUM_IP6_UDP|CSUM_IP6_TCP); } if ((mask & IFCAP_RXCSUM_IPV6) != 0 && (if_getcapabilities(ifp) & IFCAP_RXCSUM_IPV6) != 0) { @@ -2124,41 +2203,33 @@ ure_rtl8152_nic_reset(struct ure_softc *sc) static void ure_rxcsum(int capenb, struct ure_rxpkt *rp, struct mbuf *m) { - int flags; uint32_t csum, misc; - int tcp, udp; m->m_pkthdr.csum_flags = 0; - if (!(capenb & IFCAP_RXCSUM)) - return; - csum = le32toh(rp->ure_csum); misc = le32toh(rp->ure_misc); - tcp = udp = 0; - - flags = 0; - if (csum & URE_RXPKT_IPV4_CS) - flags |= CSUM_IP_CHECKED; - else if (csum & URE_RXPKT_IPV6_CS) - flags = 0; - - tcp = rp->ure_csum & URE_RXPKT_TCP_CS; - udp = rp->ure_csum & URE_RXPKT_UDP_CS; + if ((capenb & IFCAP_RXCSUM) == 0 && + (csum & URE_RXPKT_IPV4_CS) != 0) + return; + if ((capenb & IFCAP_RXCSUM_IPV6) == 0 && + (csum & URE_RXPKT_IPV6_CS) != 0) + return; - if (__predict_true((flags & CSUM_IP_CHECKED) && - !(misc & URE_RXPKT_IP_F))) { - flags |= CSUM_IP_VALID; + if ((csum & URE_RXPKT_IPV4_CS) != 0) { + m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED; + if (__predict_true((misc & URE_RXPKT_IP_F) == 0)) + m->m_pkthdr.csum_flags |= CSUM_IP_VALID; } if (__predict_true( - (tcp && !(misc & URE_RXPKT_TCP_F)) || - (udp && !(misc & URE_RXPKT_UDP_F)))) { - flags |= CSUM_DATA_VALID|CSUM_PSEUDO_HDR; + ((rp->ure_csum & URE_RXPKT_TCP_CS) != 0 && + (misc & URE_RXPKT_TCP_F) == 0) || + ((rp->ure_csum & URE_RXPKT_UDP_CS) != 0 && + (misc & URE_RXPKT_UDP_F) == 0))) { + m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | CSUM_PSEUDO_HDR; m->m_pkthdr.csum_data = 0xFFFF; } - - m->m_pkthdr.csum_flags = flags; } /* @@ -2176,7 +2247,6 @@ ure_txcsum(struct mbuf *m, int caps, uint32_t *regout) struct ip ip; struct ether_header *eh; int flags; - uint32_t data; uint32_t reg; int l3off, l4off; uint16_t type; @@ -2211,10 +2281,9 @@ ure_txcsum(struct mbuf *m, int caps, uint32_t *regout) if (flags & CSUM_IP) reg |= URE_TXPKT_IPV4_CS; - data = m->m_pkthdr.csum_data; if (flags & (CSUM_IP_TCP | CSUM_IP_UDP)) { m_copydata(m, l3off, sizeof ip, (caddr_t)&ip); - l4off = l3off + (ip.ip_hl << 2) + data; + l4off = l3off + (ip.ip_hl << 2); if (__predict_false(l4off > URE_L4_OFFSET_MAX)) return (1); @@ -2227,7 +2296,9 @@ ure_txcsum(struct mbuf *m, int caps, uint32_t *regout) } #ifdef INET6 else if (flags & (CSUM_IP6_TCP | CSUM_IP6_UDP)) { - l4off = l3off + data; + l4off = ip6_lasthdr(m, l3off, IPPROTO_IPV6, NULL); + if (__predict_false(l4off < 0)) + return (1); if (__predict_false(l4off > URE_L4_OFFSET_MAX)) return (1); diff --git a/sys/dev/usb/net/uhso.c b/sys/dev/usb/net/uhso.c index 24135f6ccd5a..16c182fcbd41 100644 --- a/sys/dev/usb/net/uhso.c +++ b/sys/dev/usb/net/uhso.c @@ -484,7 +484,7 @@ static device_method_t uhso_methods[] = { DEVMETHOD(device_probe, uhso_probe), DEVMETHOD(device_attach, uhso_attach), DEVMETHOD(device_detach, uhso_detach), - { 0, 0 } + DEVMETHOD_END }; static driver_t uhso_driver = { diff --git a/sys/dev/usb/quirk/usb_quirk.c b/sys/dev/usb/quirk/usb_quirk.c index 04441b2a344b..303f76f37fb0 100644 --- a/sys/dev/usb/quirk/usb_quirk.c +++ b/sys/dev/usb/quirk/usb_quirk.c @@ -532,7 +532,7 @@ static struct usb_quirk_entry usb_quirks[USB_DEV_QUIRKS_MAX] = { UQ_MSC_NO_INQUIRY, UQ_CFG_INDEX_0), USB_QUIRK(SMART2, G2MEMKEY, UQ_MSC_NO_INQUIRY), USB_QUIRK_REV(RALINK, RT_STOR, 0x0001, 0x0001, UQ_MSC_IGNORE), - USB_QUIRK(REALTEK, RTW8821CU_CD, UQ_MSC_IGNORE), + USB_QUIRK(REALTEK, RTW8821CU_CD, UQ_MSC_EJECT_SCSIEJECT), /* Non-standard USB MIDI devices */ USB_QUIRK(ROLAND, UM1, UQ_AU_VENDOR_CLASS), USB_QUIRK(ROLAND, SC8850, UQ_AU_VENDOR_CLASS), diff --git a/sys/dev/usb/serial/uvscom.c b/sys/dev/usb/serial/uvscom.c index b9add5c1b37b..c5086f7e86cf 100644 --- a/sys/dev/usb/serial/uvscom.c +++ b/sys/dev/usb/serial/uvscom.c @@ -551,8 +551,9 @@ uvscom_pre_param(struct ucom_softc *ucom, struct termios *t) case B38400: case B57600: case B115200: + break; default: - return (EINVAL); + return (EINVAL); } return (0); } diff --git a/sys/dev/usb/storage/umass.c b/sys/dev/usb/storage/umass.c index cacf4ddf8f16..0ee6ea992fa7 100644 --- a/sys/dev/usb/storage/umass.c +++ b/sys/dev/usb/storage/umass.c @@ -115,6 +115,7 @@ #include <sys/sx.h> #include <sys/unistd.h> #include <sys/callout.h> +#include <sys/eventhandler.h> #include <sys/malloc.h> #include <sys/priv.h> @@ -124,6 +125,7 @@ #include "usbdevs.h" #include <dev/usb/quirk/usb_quirk.h> +#include <dev/usb/usb_msctest.h> #include <cam/cam.h> #include <cam/cam_ccb.h> @@ -705,6 +707,59 @@ static const uint8_t fake_inq_data[SHORT_INQUIRY_LENGTH] = { #define UFI_COMMAND_LENGTH 12 /* UFI commands are always 12 bytes */ #define ATAPI_COMMAND_LENGTH 12 /* ATAPI commands are always 12 bytes */ +static void +umass_autoinst_eject_quirks(void *arg __unused, struct usb_device *udev, + struct usb_attach_arg *uaa) +{ + struct usb_interface *iface; + struct usb_interface_descriptor *id; + + if (uaa->dev_state != UAA_DEV_READY) + return; + + iface = usbd_get_iface(udev, 0); + if (iface == NULL) + return; + + id = iface->idesc; + if (id == NULL || id->bInterfaceClass != UICLASS_MASS) + return; + + if (usb_test_quirk(uaa, UQ_MSC_EJECT_SCSIEJECT)) { + int error; + + error = usb_msc_eject(uaa->device, 0, MSC_EJECT_STOPUNIT); + if (error == 0) + uaa->dev_state = UAA_DEV_EJECTING; + else + printf("UMASS failed to eject by SCSI eject STOPUNIT " + "command based on quirk: %d\n", error); + } +} + +static eventhandler_tag umass_drv_evh_tag; + +static int +umass_driver_evh(struct module *mod, int what, void *arg) +{ + + switch (what) { + case MOD_LOAD: + umass_drv_evh_tag = EVENTHANDLER_REGISTER(usb_dev_configured, + umass_autoinst_eject_quirks, NULL, EVENTHANDLER_PRI_ANY); + break; + case MOD_UNLOAD: + if (umass_drv_evh_tag != NULL) + EVENTHANDLER_DEREGISTER(usb_dev_configured, + umass_drv_evh_tag); + break; + default: + return (EOPNOTSUPP); + } + + return (0); +} + static device_method_t umass_methods[] = { /* Device interface */ DEVMETHOD(device_probe, umass_probe), @@ -725,7 +780,7 @@ static const STRUCT_USB_HOST_ID __used umass_devs[] = { {USB_IFACE_CLASS(UICLASS_MASS),}, }; -DRIVER_MODULE(umass, uhub, umass_driver, NULL, NULL); +DRIVER_MODULE(umass, uhub, umass_driver, umass_driver_evh, NULL); MODULE_DEPEND(umass, usb, 1, 1, 1); MODULE_DEPEND(umass, cam, 1, 1, 1); MODULE_VERSION(umass, 1); diff --git a/sys/dev/usb/usb.h b/sys/dev/usb/usb.h index a6c3c8030c73..3e972f876c6a 100644 --- a/sys/dev/usb/usb.h +++ b/sys/dev/usb/usb.h @@ -541,7 +541,7 @@ struct usb_endpoint_descriptor { #define UE_XFERTYPE 0x03 #define UE_CONTROL 0x00 #define UE_ISOCHRONOUS 0x01 -#define UE_BULK 0x02 +#define UE_BULK 0x02 #define UE_INTERRUPT 0x03 #define UE_BULK_INTR 0xfe /* for internal use only! */ #define UE_TYPE_ANY 0xff /* for internal use only! */ diff --git a/sys/dev/usb/usb_device.c b/sys/dev/usb/usb_device.c index f0989972f49f..4e0268110787 100644 --- a/sys/dev/usb/usb_device.c +++ b/sys/dev/usb/usb_device.c @@ -3127,7 +3127,7 @@ usbd_fill_deviceinfo(struct usb_device *udev, struct usb_device_info *di) { struct usb_device *hub; - bzero(di, sizeof(di[0])); + memset(di, 0, sizeof(di[0])); di->udi_bus = device_get_unit(udev->bus->bdev); di->udi_addr = udev->address; diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs index bb039f59ce19..e1394e903cb3 100644 --- a/sys/dev/usb/usbdevs +++ b/sys/dev/usb/usbdevs @@ -786,6 +786,7 @@ vendor PERASO 0x2932 Peraso Technologies, Inc. vendor PLANEX 0x2c02 Planex Communications vendor MERCUSYS 0x2c4e Mercusys, Inc. vendor QUECTEL 0x2c7c Quectel Wireless Solutions +vendor NUAND 0x2cf0 Nuand LLC vendor VIDZMEDIA 0x3275 VidzMedia Pte Ltd vendor LINKINSTRUMENTS 0x3195 Link Instruments Inc. vendor AEI 0x3334 AEI @@ -1695,6 +1696,7 @@ product CYBERTAN RT2870 0x1828 RT2870 /* Cypress Semiconductor products */ product CYPRESS MOUSE 0x0001 mouse product CYPRESS THERMO 0x0002 thermometer +product CYPRESS FX3 0x00f3 EZ-USB FX3 product CYPRESS WISPY1A 0x0bad MetaGeek Wi-Spy product CYPRESS KBDHUB 0x0101 Keyboard/Hub product CYPRESS FMRADIO 0x1002 FM Radio @@ -1773,6 +1775,7 @@ product DIGIANSWER ZIGBEE802154 0x000a ZigBee/802.15.4 MAC /* D-Link products */ /*product DLINK DSBS25 0x0100 DSB-S25 serial*/ +product DLINK DUBE1312 0xb301 DUB-E1312 USB Ethernet product DLINK DUBE100 0x1a00 10/100 Ethernet product DLINK DUBE100C1 0x1a02 DUB-E100 rev C1 product DLINK DSB650TX4 0x200c 10/100 Ethernet @@ -3373,6 +3376,8 @@ product MICROSOFT WLNOTEBOOK3 0x00d2 Wireless Optical Mouse 3000 (Model 1049) product MICROSOFT NATURAL4000 0x00db Natural Ergonomic Keyboard 4000 product MICROSOFT WLNOTEBOOK2 0x00e1 Wireless Optical Mouse 3000 (Model 1056) product MICROSOFT XBOX360 0x0292 XBOX 360 WLAN +product MICROSOFT SURFETH1 0x07ab Surface USB Ethernet +product MICROSOFT SURFETH2 0x07c6 Surface USB Ethernet product MICROSOFT WINDEVETH 0x0c5e Windows Dev Kit 2023 Ethernet /* Microtech products */ @@ -3556,6 +3561,11 @@ product NIKON E990 0x0102 Digital Camera E990 product NIKON LS40 0x4000 CoolScan LS40 ED product NIKON D300 0x041a Digital Camera D300 +/* Nuand LLC products */ +product NUAND BLADERF 0x5246 bladeRF Software Defined Radio +product NUAND BLADERF_BL 0x5247 bladeRF Bootloader +product NUAND BLADERF2 0x5250 bladeRF 2.0 Software Defined Radio + /* NovaTech Products */ product NOVATECH NV902 0x9020 NovaTech NV-902W product NOVATECH RT2573 0x9021 RT2573 @@ -4122,6 +4132,8 @@ product REALTEK RTL8821AU_2 0x0811 RTL8821AU product REALTEK RTW8821CU_CD 0x1a2b RTW8821CU_CD product REALTEK RTL8188RU_2 0x317f RTL8188RU product REALTEK USBKR100 0x8150 USBKR100 USB Ethernet +product REALTEK RTL8050 0x8050 RTL8050 USB Ethernet +product REALTEK RTL8053 0x8053 RTL8053 USB Ethernet product REALTEK RTL8152 0x8152 RTL8152 USB Ethernet product REALTEK RTL8153 0x8153 RTL8153 USB Ethernet product REALTEK RTL8156 0x8156 RTL8156 USB Ethernet @@ -4214,6 +4226,7 @@ product SAGEM XG760A 0x004a XG-760A product SAGEM XG76NA 0x0062 XG-76NA /* Samsung products */ +product SAMSUNG RTL8153 0xa101 USB Ethernet product SAMSUNG WIS09ABGN 0x2018 WIS09ABGN Wireless LAN adapter product SAMSUNG ML6060 0x3008 ML-6060 laser printer product SAMSUNG YP_U2 0x5050 YP-U2 MP3 Player @@ -4845,6 +4858,7 @@ product TPLINK T2UNANO 0x011e Archer T2U Nano product TPLINK T2UV3 0x011f Archer T2U ver 3 product TPLINK T2UPLUS 0x0120 Archer T2U Plus product TPLINK RTL8153 0x0601 RTL8153 USB 10/100/1000 LAN +product TPLINK RTL8153_2 0x0602 RTL8153 USB 10/100/1000 LAN /* Trek Technology products */ product TREK THUMBDRIVE 0x1111 ThumbDrive diff --git a/sys/dev/usb/wlan/if_mtw.c b/sys/dev/usb/wlan/if_mtw.c index 8384c0a2d9fc..9d256056f6b2 100644 --- a/sys/dev/usb/wlan/if_mtw.c +++ b/sys/dev/usb/wlan/if_mtw.c @@ -64,6 +64,7 @@ #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> +#include <dev/usb/usb_request.h> #include "usbdevs.h" @@ -525,6 +526,15 @@ mtw_attach(device_t self) sc->sc_dev = self; sc->sc_sent = 0; + /* + * Reset the device to clear any stale state left over from + * a previous warm reboot. Some MT7601U devices fail otherwise. + */ + error = usbd_req_re_enumerate(uaa->device, NULL); + if (error != 0) + device_printf(self, "USB re-enumerate failed, continuing\n"); + DELAY(100000); /* 100ms settle time */ + mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev), MTX_NETWORK_LOCK, MTX_DEF); @@ -585,7 +595,7 @@ mtw_attach(device_t self) sc->mac_rev = tmp & 0xffff; mtw_load_microcode(sc); - ret = msleep(&sc->fwloading, &sc->sc_mtx, 0, "fwload", 3 * hz); + ret = msleep(&sc->fwloading, &sc->sc_mtx, 0, "fwload", 10 * hz); if (ret == EWOULDBLOCK || sc->fwloading != 1) { device_printf(sc->sc_dev, "timeout waiting for MCU to initialize\n"); @@ -1105,11 +1115,22 @@ mtw_load_microcode(void *arg) // int ntries; int dlen, ilen; device_printf(sc->sc_dev, "version:0x%hx\n", sc->asic_ver); - /* is firmware already running? */ + /* + * Firmware may still be running from a previous warm reboot. + * Force a reset of the MCU to ensure a clean state. + */ mtw_read_cfg(sc, MTW_MCU_DMA_ADDR, &tmp); if (tmp == MTW_MCU_READY) { - return; + device_printf(sc->sc_dev, "MCU already running, resetting\n"); + mtw_write(sc, MTW_MCU_RESET_CTL, MTW_RESET); + DELAY(10000); + mtw_write(sc, MTW_MCU_RESET_CTL, 0); + DELAY(10000); + /* Clear ready flag */ + mtw_write_cfg(sc, MTW_MCU_DMA_ADDR, 0); + DELAY(1000); } + if (sc->asic_ver == 0x7612) { fwname = "mtw-mt7662u_rom_patch"; @@ -2856,7 +2877,7 @@ mtw_fw_callback(struct usb_xfer *xfer, usb_error_t error) } mtw_delay(sc, 10); - for (ntries = 0; ntries < 100; ntries++) { + for (ntries = 0; ntries < 300; ntries++) { if ((error = mtw_read_cfg(sc, MTW_MCU_DMA_ADDR, &tmp)) != 0) { device_printf(sc->sc_dev, @@ -2870,9 +2891,9 @@ mtw_fw_callback(struct usb_xfer *xfer, usb_error_t error) break; } - mtw_delay(sc, 10); + mtw_delay(sc, 30); } - if (ntries == 100) + if (ntries == 300) sc->fwloading = 0; wakeup(&sc->fwloading); return; diff --git a/sys/dev/usb/wlan/if_rsu.c b/sys/dev/usb/wlan/if_rsu.c index e976948f6849..2f934737f699 100644 --- a/sys/dev/usb/wlan/if_rsu.c +++ b/sys/dev/usb/wlan/if_rsu.c @@ -1724,7 +1724,8 @@ rsu_set_key_group(struct rsu_softc *sc, const struct ieee80211_key *k) RSU_ASSERT_LOCKED(sc); /* Map net80211 cipher to HW crypto algorithm. */ - algo = rsu_crypto_mode(sc, k->wk_cipher->ic_cipher, k->wk_keylen); + algo = rsu_crypto_mode(sc, k->wk_cipher->ic_cipher, + ieee80211_crypto_get_key_len(k)); if (algo == R92S_KEY_ALGO_INVALID) return (EINVAL); @@ -1732,13 +1733,14 @@ rsu_set_key_group(struct rsu_softc *sc, const struct ieee80211_key *k) key.algo = algo; key.cam_id = k->wk_keyix; key.grpkey = (k->wk_flags & IEEE80211_KEY_GROUP) != 0; - memcpy(key.key, k->wk_key, MIN(k->wk_keylen, sizeof(key.key))); + memcpy(key.key, ieee80211_crypto_get_key_data(k), + MIN(ieee80211_crypto_get_key_len(k), sizeof(key.key))); RSU_DPRINTF(sc, RSU_DEBUG_KEY | RSU_DEBUG_FWCMD, "%s: keyix %u, group %u, algo %u/%u, flags %04X, len %u, " "macaddr %s\n", __func__, key.cam_id, key.grpkey, - k->wk_cipher->ic_cipher, key.algo, k->wk_flags, k->wk_keylen, - ether_sprintf(k->wk_macaddr)); + k->wk_cipher->ic_cipher, key.algo, k->wk_flags, + ieee80211_crypto_get_key_len(k), ether_sprintf(k->wk_macaddr)); error = rsu_fw_cmd(sc, R92S_CMD_SET_KEY, &key, sizeof(key)); if (error != 0) { @@ -1764,19 +1766,22 @@ rsu_set_key_pair(struct rsu_softc *sc, const struct ieee80211_key *k) return (ESHUTDOWN); /* Map net80211 cipher to HW crypto algorithm. */ - algo = rsu_crypto_mode(sc, k->wk_cipher->ic_cipher, k->wk_keylen); + algo = rsu_crypto_mode(sc, k->wk_cipher->ic_cipher, + ieee80211_crypto_get_key_len(k)); if (algo == R92S_KEY_ALGO_INVALID) return (EINVAL); memset(&key, 0, sizeof(key)); key.algo = algo; memcpy(key.macaddr, k->wk_macaddr, sizeof(key.macaddr)); - memcpy(key.key, k->wk_key, MIN(k->wk_keylen, sizeof(key.key))); + memcpy(key.key, ieee80211_crypto_get_key_data(k), + MIN(ieee80211_crypto_get_key_len(k), sizeof(key.key))); RSU_DPRINTF(sc, RSU_DEBUG_KEY | RSU_DEBUG_FWCMD, "%s: keyix %u, algo %u/%u, flags %04X, len %u, macaddr %s\n", __func__, k->wk_keyix, k->wk_cipher->ic_cipher, key.algo, - k->wk_flags, k->wk_keylen, ether_sprintf(key.macaddr)); + k->wk_flags, ieee80211_crypto_get_key_len(k), + ether_sprintf(key.macaddr)); error = rsu_fw_cmd(sc, R92S_CMD_SET_STA_KEY, &key, sizeof(key)); if (error != 0) { diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c index b822766f0ba5..4a4a150146a1 100644 --- a/sys/dev/usb/wlan/if_rum.c +++ b/sys/dev/usb/wlan/if_rum.c @@ -193,8 +193,8 @@ static uint32_t rum_read(struct rum_softc *, uint16_t); static void rum_read_multi(struct rum_softc *, uint16_t, void *, int); static usb_error_t rum_write(struct rum_softc *, uint16_t, uint32_t); -static usb_error_t rum_write_multi(struct rum_softc *, uint16_t, void *, - size_t); +static usb_error_t rum_write_multi(struct rum_softc *, uint16_t, + const void *, size_t); static usb_error_t rum_setbits(struct rum_softc *, uint16_t, uint32_t); static usb_error_t rum_clrbits(struct rum_softc *, uint16_t, uint32_t); static usb_error_t rum_modbits(struct rum_softc *, uint16_t, uint32_t, @@ -1460,7 +1460,8 @@ rum_tx_crypto_flags(struct rum_softc *sc, struct ieee80211_node *ni, if (!(k->wk_flags & IEEE80211_KEY_SWCRYPT)) { cipher = k->wk_cipher->ic_cipher; pos = k->wk_keyix; - mode = rum_crypto_mode(sc, cipher, k->wk_keylen); + mode = rum_crypto_mode(sc, cipher, + ieee80211_crypto_get_key_len(k)); if (mode == 0) return 0; @@ -1843,7 +1844,8 @@ rum_write(struct rum_softc *sc, uint16_t reg, uint32_t val) } static usb_error_t -rum_write_multi(struct rum_softc *sc, uint16_t reg, void *buf, size_t len) +rum_write_multi(struct rum_softc *sc, uint16_t reg, const void *buf, + size_t len) { struct usb_device_request req; usb_error_t error; @@ -1858,7 +1860,8 @@ rum_write_multi(struct rum_softc *sc, uint16_t reg, void *buf, size_t len) USETW(req.wIndex, reg + offset); USETW(req.wLength, MIN(len - offset, 64)); - error = rum_do_request(sc, &req, (char *)buf + offset); + error = rum_do_request(sc, &req, __DECONST(char *, buf) + + offset); if (error != 0) { device_printf(sc->sc_dev, "could not multi write MAC register: %s\n", @@ -2859,15 +2862,16 @@ rum_common_key_set(struct rum_softc *sc, struct ieee80211_key *k, uint16_t base) { - if (rum_write_multi(sc, base, k->wk_key, k->wk_keylen)) + if (rum_write_multi(sc, base, ieee80211_crypto_get_key_data(k), + ieee80211_crypto_get_key_len(k))) return EIO; if (k->wk_cipher->ic_cipher == IEEE80211_CIPHER_TKIP) { if (rum_write_multi(sc, base + IEEE80211_KEYBUF_SIZE, - k->wk_txmic, 8)) + ieee80211_crypto_get_key_txmic_data(k), 8)) return EIO; if (rum_write_multi(sc, base + IEEE80211_KEYBUF_SIZE + 8, - k->wk_rxmic, 8)) + ieee80211_crypto_get_key_rxmic_data(k), 8)) return EIO; } @@ -2886,7 +2890,8 @@ rum_group_key_set_cb(struct rum_softc *sc, union sec_param *data, sc->sc_clr_shkeys = 1; } - mode = rum_crypto_mode(sc, k->wk_cipher->ic_cipher, k->wk_keylen); + mode = rum_crypto_mode(sc, k->wk_cipher->ic_cipher, + ieee80211_crypto_get_key_len(k)); if (mode == 0) goto print_err; @@ -2941,7 +2946,8 @@ rum_pair_key_set_cb(struct rum_softc *sc, union sec_param *data, uint8_t buf[IEEE80211_ADDR_LEN + 1]; uint8_t mode; - mode = rum_crypto_mode(sc, k->wk_cipher->ic_cipher, k->wk_keylen); + mode = rum_crypto_mode(sc, k->wk_cipher->ic_cipher, + ieee80211_crypto_get_key_len(k)); if (mode == 0) goto print_err; diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c index 147aa4044057..7d993caaf2a3 100644 --- a/sys/dev/usb/wlan/if_run.c +++ b/sys/dev/usb/wlan/if_run.c @@ -2375,7 +2375,7 @@ run_key_set_cb(void *arg) /* map net80211 cipher to RT2860 security mode */ switch (cipher) { case IEEE80211_CIPHER_WEP: - if(k->wk_keylen < 8) + if(ieee80211_crypto_get_key_len(k) < 8) /* TODO: add a specific WEP40/WEP104 call! */ mode = RT2860_MODE_WEP40; else mode = RT2860_MODE_WEP104; @@ -2408,15 +2408,20 @@ run_key_set_cb(void *arg) } if (cipher == IEEE80211_CIPHER_TKIP) { - if(run_write_region_1(sc, base, k->wk_key, 16)) + if (run_write_region_1(sc, base, + ieee80211_crypto_get_key_data(k), 16)) return; - if(run_write_region_1(sc, base + 16, &k->wk_key[16], 8)) /* wk_txmic */ + if (run_write_region_1(sc, base + 16, + ieee80211_crypto_get_key_txmic_data(k), 8)) /* wk_txmic */ return; - if(run_write_region_1(sc, base + 24, &k->wk_key[24], 8)) /* wk_rxmic */ + if (run_write_region_1(sc, base + 24, + ieee80211_crypto_get_key_rxmic_data(k), 8)) /* wk_rxmic */ return; } else { /* roundup len to 16-bit: XXX fix write_region_1() instead */ - if(run_write_region_1(sc, base, k->wk_key, (k->wk_keylen + 1) & ~1)) + if (run_write_region_1(sc, base, + ieee80211_crypto_get_key_data(k), + (ieee80211_crypto_get_key_len(k) + 1) & ~1)) return; } diff --git a/sys/dev/virtio/block/virtio_blk.c b/sys/dev/virtio/block/virtio_blk.c index 5eb681128e9c..96846eb0529a 100644 --- a/sys/dev/virtio/block/virtio_blk.c +++ b/sys/dev/virtio/block/virtio_blk.c @@ -59,10 +59,15 @@ struct vtblk_request { struct vtblk_softc *vbr_sc; bus_dmamap_t vbr_mapp; + struct virtio_blk_outhdr *vbr_hdr; + vm_paddr_t vbr_hdr_paddr; + bus_dmamap_t vbr_hdr_mapp; + uint8_t *vbr_ack; + vm_paddr_t vbr_ack_paddr; + bus_dmamap_t vbr_ack_mapp; + /* Fields after this point are zeroed for each request. */ - struct virtio_blk_outhdr vbr_hdr; struct bio *vbr_bp; - uint8_t vbr_ack; uint8_t vbr_requeue_on_error; uint8_t vbr_busdma_wait; int vbr_error; @@ -78,6 +83,8 @@ enum vtblk_cache_mode { struct vtblk_softc { device_t vtblk_dev; struct mtx vtblk_mtx; + struct mtx vtblk_hdr_mtx; + struct mtx vtblk_ack_mtx; uint64_t vtblk_features; uint32_t vtblk_flags; #define VTBLK_FLAG_INDIRECT 0x0001 @@ -91,6 +98,8 @@ struct vtblk_softc { struct virtqueue *vtblk_vq; struct sglist *vtblk_sglist; bus_dma_tag_t vtblk_dmat; + bus_dma_tag_t vtblk_hdr_dmat; + bus_dma_tag_t vtblk_ack_dmat; struct disk *vtblk_disk; struct bio_queue_head vtblk_bioq; @@ -385,7 +394,7 @@ vtblk_attach(device_t dev) maxphys, /* max request size */ sc->vtblk_max_nsegs - VTBLK_MIN_SEGMENTS, /* max # segments */ maxphys, /* maxsegsize */ - 0, /* flags */ + BUS_DMA_COHERENT, /* flags */ busdma_lock_mutex, /* lockfunc */ &sc->vtblk_mtx, /* lockarg */ &sc->vtblk_dmat); @@ -394,6 +403,46 @@ vtblk_attach(device_t dev) goto fail; } + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + (sc->vtblk_flags & VTBLK_FLAG_BUSDMA_ALIGN) ? PAGE_SIZE : + sizeof(struct virtio_blk_outhdr), /* alignment */ + 0, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + sizeof(struct virtio_blk_outhdr), /* max request size */ + 1, /* max # segments */ + sizeof(struct virtio_blk_outhdr), /* maxsegsize */ + BUS_DMA_COHERENT, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &sc->vtblk_hdr_mtx, /* lockarg */ + &sc->vtblk_hdr_dmat); + if (error) { + device_printf(dev, "cannot create hdr bus dma tag\n"); + goto fail; + } + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + (sc->vtblk_flags & VTBLK_FLAG_BUSDMA_ALIGN) ? PAGE_SIZE : + sizeof(uint8_t), /* alignment */ + 0, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + sizeof(uint8_t), /* max request size */ + 1, /* max # segments */ + sizeof(uint8_t), /* maxsegsize */ + BUS_DMA_COHERENT, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &sc->vtblk_ack_mtx, /* lockarg */ + &sc->vtblk_ack_dmat); + if (error) { + device_printf(dev, "cannot create ack bus dma tag\n"); + goto fail; + } + #ifdef __powerpc__ /* * Virtio uses physical addresses rather than bus addresses, so we @@ -401,6 +450,8 @@ vtblk_attach(device_t dev) * present, this is only a thing on the powerpc architectures. */ bus_dma_tag_set_iommu(sc->vtblk_dmat, NULL, NULL); + bus_dma_tag_set_iommu(sc->vtblk_hdr_dmat, NULL, NULL); + bus_dma_tag_set_iommu(sc->vtblk_ack_dmat, NULL, NULL); #endif error = vtblk_alloc_virtqueue(sc); @@ -452,6 +503,16 @@ vtblk_detach(device_t dev) sc->vtblk_disk = NULL; } + if (sc->vtblk_ack_dmat != NULL) { + bus_dma_tag_destroy(sc->vtblk_ack_dmat); + sc->vtblk_ack_dmat = NULL; + } + + if (sc->vtblk_hdr_dmat != NULL) { + bus_dma_tag_destroy(sc->vtblk_hdr_dmat); + sc->vtblk_hdr_dmat = NULL; + } + if (sc->vtblk_dmat != NULL) { bus_dma_tag_destroy(sc->vtblk_dmat); sc->vtblk_dmat = NULL; @@ -839,11 +900,88 @@ vtblk_create_disk(struct vtblk_softc *sc) disk_create(dp, DISK_VERSION); } +static void +vtblk_ack_load_callback(void *arg, bus_dma_segment_t *segs, int nsegs, + int error) +{ + struct vtblk_request *req; + + if (error != 0) + return; + + KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); + + req = (struct vtblk_request *)arg; + req->vbr_ack_paddr = segs[0].ds_addr; +} + +static void +vtblk_hdr_load_callback(void *arg, bus_dma_segment_t *segs, int nsegs, + int error) +{ + struct vtblk_request *req; + + if (error != 0) + return; + + KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); + + req = (struct vtblk_request *)arg; + req->vbr_hdr_paddr = segs[0].ds_addr; +} + +static int +vtblk_create_request(struct vtblk_softc *sc, struct vtblk_request *req) +{ + req->vbr_sc = sc; + + if (bus_dmamap_create(sc->vtblk_dmat, 0, &req->vbr_mapp)) + goto error_free; + + if (bus_dmamem_alloc(sc->vtblk_hdr_dmat, (void **)&req->vbr_hdr, + BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, + &req->vbr_hdr_mapp)) + goto error_destroy; + + if (bus_dmamem_alloc(sc->vtblk_ack_dmat, (void **)&req->vbr_ack, + BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, + &req->vbr_ack_mapp)) + goto error_hdr_free; + + MPASS(sglist_count(req->vbr_hdr, sizeof(*req->vbr_hdr)) == 1); + MPASS(sglist_count(req->vbr_ack, sizeof(*req->vbr_ack)) == 1); + + if (bus_dmamap_load(sc->vtblk_hdr_dmat, req->vbr_hdr_mapp, + req->vbr_hdr, sizeof(struct virtio_blk_outhdr), + vtblk_hdr_load_callback, req, BUS_DMA_NOWAIT)) + goto error_ack_free; + + if (bus_dmamap_load(sc->vtblk_ack_dmat, req->vbr_ack_mapp, + req->vbr_ack, sizeof(uint8_t), vtblk_ack_load_callback, + req, BUS_DMA_NOWAIT)) + goto error_hdr_unload; + + return (0); + +error_hdr_unload: + bus_dmamap_unload(sc->vtblk_hdr_dmat, req->vbr_hdr_mapp); +error_ack_free: + bus_dmamem_free(sc->vtblk_ack_dmat, req->vbr_ack, req->vbr_ack_mapp); +error_hdr_free: + bus_dmamem_free(sc->vtblk_hdr_dmat, req->vbr_hdr, req->vbr_hdr_mapp); +error_destroy: + bus_dmamap_destroy(sc->vtblk_dmat, req->vbr_mapp); +error_free: + + return (ENOMEM); +} + static int vtblk_request_prealloc(struct vtblk_softc *sc) { struct vtblk_request *req; int i, nreqs; + int error; nreqs = virtqueue_size(sc->vtblk_vq); @@ -860,20 +998,19 @@ vtblk_request_prealloc(struct vtblk_softc *sc) if (req == NULL) return (ENOMEM); - req->vbr_sc = sc; - if (bus_dmamap_create(sc->vtblk_dmat, 0, &req->vbr_mapp)) { + error = vtblk_create_request(sc, req); + if (error) { free(req, M_DEVBUF); - return (ENOMEM); + return (error); } - MPASS(sglist_count(&req->vbr_hdr, sizeof(req->vbr_hdr)) == 1); - MPASS(sglist_count(&req->vbr_ack, sizeof(req->vbr_ack)) == 1); - sc->vtblk_request_count++; vtblk_request_enqueue(sc, req); } - return (0); + error = vtblk_create_request(sc, &sc->vtblk_dump_request); + + return (error); } static void @@ -885,8 +1022,13 @@ vtblk_request_free(struct vtblk_softc *sc) while ((req = vtblk_request_dequeue(sc)) != NULL) { sc->vtblk_request_count--; + bus_dmamap_unload(sc->vtblk_ack_dmat, req->vbr_ack_mapp); + bus_dmamem_free(sc->vtblk_ack_dmat, req->vbr_ack, + req->vbr_ack_mapp); + bus_dmamap_unload(sc->vtblk_hdr_dmat, req->vbr_hdr_mapp); + bus_dmamem_free(sc->vtblk_hdr_dmat, req->vbr_hdr, + req->vbr_hdr_mapp); bus_dmamap_destroy(sc->vtblk_dmat, req->vbr_mapp); - free(req, M_DEVBUF); } KASSERT(sc->vtblk_request_count == 0, @@ -901,8 +1043,10 @@ vtblk_request_dequeue(struct vtblk_softc *sc) req = TAILQ_FIRST(&sc->vtblk_req_free); if (req != NULL) { TAILQ_REMOVE(&sc->vtblk_req_free, req, vbr_link); - bzero(&req->vbr_hdr, sizeof(struct vtblk_request) - - offsetof(struct vtblk_request, vbr_hdr)); + bzero(req->vbr_hdr, sizeof(struct virtio_blk_outhdr)); + *req->vbr_ack = 0; + bzero(&req->vbr_bp, sizeof(struct vtblk_request) - + offsetof(struct vtblk_request, vbr_bp)); } return (req); @@ -965,32 +1109,35 @@ vtblk_request_bio(struct vtblk_softc *sc) bp = bioq_takefirst(bioq); req->vbr_bp = bp; - req->vbr_ack = -1; - req->vbr_hdr.ioprio = vtblk_gtoh32(sc, 1); + *req->vbr_ack = -1; + req->vbr_hdr->ioprio = vtblk_gtoh32(sc, 1); switch (bp->bio_cmd) { case BIO_FLUSH: - req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_FLUSH); - req->vbr_hdr.sector = 0; + req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_FLUSH); + req->vbr_hdr->sector = 0; break; case BIO_READ: - req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_IN); - req->vbr_hdr.sector = vtblk_gtoh64(sc, bp->bio_offset / VTBLK_BSIZE); + req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_IN); + req->vbr_hdr->sector = vtblk_gtoh64(sc, bp->bio_offset / + VTBLK_BSIZE); break; case BIO_WRITE: - req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_OUT); - req->vbr_hdr.sector = vtblk_gtoh64(sc, bp->bio_offset / VTBLK_BSIZE); + req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_OUT); + req->vbr_hdr->sector = vtblk_gtoh64(sc, bp->bio_offset / + VTBLK_BSIZE); break; case BIO_DELETE: - req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_DISCARD); - req->vbr_hdr.sector = vtblk_gtoh64(sc, bp->bio_offset / VTBLK_BSIZE); + req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_DISCARD); + req->vbr_hdr->sector = vtblk_gtoh64(sc, bp->bio_offset / + VTBLK_BSIZE); break; default: panic("%s: bio with unhandled cmd: %d", __func__, bp->bio_cmd); } if (bp->bio_flags & BIO_ORDERED) - req->vbr_hdr.type |= vtblk_gtoh32(sc, VIRTIO_BLK_T_BARRIER); + req->vbr_hdr->type |= vtblk_gtoh32(sc, VIRTIO_BLK_T_BARRIER); return (req); } @@ -1072,13 +1219,17 @@ vtblk_request_execute_cb(void * callback_arg, bus_dma_segment_t * segs, goto out; } ordered = 1; - req->vbr_hdr.type &= vtblk_gtoh32(sc, + req->vbr_hdr->type &= vtblk_gtoh32(sc, ~VIRTIO_BLK_T_BARRIER); } } + bus_dmamap_sync(sc->vtblk_hdr_dmat, req->vbr_hdr_mapp, + BUS_DMASYNC_PREWRITE); + sglist_reset(sg); - sglist_append(sg, &req->vbr_hdr, sizeof(struct virtio_blk_outhdr)); + sglist_append_phys(sg, req->vbr_hdr_paddr, + sizeof(struct virtio_blk_outhdr)); if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) { /* @@ -1125,8 +1276,11 @@ vtblk_request_execute_cb(void * callback_arg, bus_dma_segment_t * segs, } } + bus_dmamap_sync(sc->vtblk_ack_dmat, req->vbr_ack_mapp, + BUS_DMASYNC_PREREAD); + writable++; - sglist_append(sg, &req->vbr_ack, sizeof(uint8_t)); + sglist_append_phys(sg, req->vbr_ack_paddr, sizeof(uint8_t)); readable = sg->sg_nseg - writable; if (req->vbr_mapp != NULL) { @@ -1168,7 +1322,10 @@ vtblk_request_error(struct vtblk_request *req) { int error; - switch (req->vbr_ack) { + bus_dmamap_sync(req->vbr_sc->vtblk_ack_dmat, req->vbr_ack_mapp, + BUS_DMASYNC_POSTREAD); + + switch (*req->vbr_ack) { case VIRTIO_BLK_S_OK: error = 0; break; @@ -1409,10 +1566,10 @@ vtblk_ident(struct vtblk_softc *sc) if (req == NULL) return; - req->vbr_ack = -1; - req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_GET_ID); - req->vbr_hdr.ioprio = vtblk_gtoh32(sc, 1); - req->vbr_hdr.sector = 0; + *req->vbr_ack = -1; + req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_GET_ID); + req->vbr_hdr->ioprio = vtblk_gtoh32(sc, 1); + req->vbr_hdr->sector = 0; req->vbr_bp = &buf; g_reset_bio(&buf); @@ -1547,10 +1704,10 @@ vtblk_dump_write(struct vtblk_softc *sc, void *virtual, off_t offset, req = &sc->vtblk_dump_request; req->vbr_sc = sc; - req->vbr_ack = -1; - req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_OUT); - req->vbr_hdr.ioprio = vtblk_gtoh32(sc, 1); - req->vbr_hdr.sector = vtblk_gtoh64(sc, offset / VTBLK_BSIZE); + *req->vbr_ack = -1; + req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_OUT); + req->vbr_hdr->ioprio = vtblk_gtoh32(sc, 1); + req->vbr_hdr->sector = vtblk_gtoh64(sc, offset / VTBLK_BSIZE); req->vbr_bp = &buf; g_reset_bio(&buf); @@ -1570,10 +1727,10 @@ vtblk_dump_flush(struct vtblk_softc *sc) req = &sc->vtblk_dump_request; req->vbr_sc = sc; - req->vbr_ack = -1; - req->vbr_hdr.type = vtblk_gtoh32(sc, VIRTIO_BLK_T_FLUSH); - req->vbr_hdr.ioprio = vtblk_gtoh32(sc, 1); - req->vbr_hdr.sector = 0; + *req->vbr_ack = -1; + req->vbr_hdr->type = vtblk_gtoh32(sc, VIRTIO_BLK_T_FLUSH); + req->vbr_hdr->ioprio = vtblk_gtoh32(sc, 1); + req->vbr_hdr->sector = 0; req->vbr_bp = &buf; g_reset_bio(&buf); diff --git a/sys/dev/virtio/gpu/virtio_gpu.c b/sys/dev/virtio/gpu/virtio_gpu.c index 668eb170304a..b95bae9fe286 100644 --- a/sys/dev/virtio/gpu/virtio_gpu.c +++ b/sys/dev/virtio/gpu/virtio_gpu.c @@ -445,21 +445,33 @@ vtgpu_alloc_virtqueue(struct vtgpu_softc *sc) } static int -vtgpu_req_resp(struct vtgpu_softc *sc, void *req, size_t reqlen, - void *resp, size_t resplen) +vtgpu_req_resp2(struct vtgpu_softc *sc, void *req1, size_t req1len, + void *req2, size_t req2len, void *resp, size_t resplen) { struct sglist sg; - struct sglist_seg segs[2]; - int error; + struct sglist_seg segs[3]; + int error, rcount; - sglist_init(&sg, 2, segs); + sglist_init(&sg, 3, segs); - error = sglist_append(&sg, req, reqlen); + rcount = 1; + error = sglist_append(&sg, req1, req1len); if (error != 0) { device_printf(sc->vtgpu_dev, - "Unable to append the request to the sglist: %d\n", error); + "Unable to append the request to the sglist: %d\n", + error); return (error); } + if (req2 != NULL) { + error = sglist_append(&sg, req2, req2len); + if (error != 0) { + device_printf(sc->vtgpu_dev, + "Unable to append the request to the sglist: %d\n", + error); + return (error); + } + rcount++; + } error = sglist_append(&sg, resp, resplen); if (error != 0) { device_printf(sc->vtgpu_dev, @@ -467,7 +479,7 @@ vtgpu_req_resp(struct vtgpu_softc *sc, void *req, size_t reqlen, error); return (error); } - error = virtqueue_enqueue(sc->vtgpu_ctrl_vq, resp, &sg, 1, 1); + error = virtqueue_enqueue(sc->vtgpu_ctrl_vq, resp, &sg, rcount, 1); if (error != 0) { device_printf(sc->vtgpu_dev, "Enqueue failed: %d\n", error); return (error); @@ -480,6 +492,13 @@ vtgpu_req_resp(struct vtgpu_softc *sc, void *req, size_t reqlen, } static int +vtgpu_req_resp(struct vtgpu_softc *sc, void *req, size_t reqlen, + void *resp, size_t resplen) +{ + return (vtgpu_req_resp2(sc, req, reqlen, NULL, 0, resp, resplen)); +} + +static int vtgpu_get_display_info(struct vtgpu_softc *sc) { struct { @@ -559,9 +578,15 @@ static int vtgpu_attach_backing(struct vtgpu_softc *sc) { struct { + /* + * Split the backing and mem request arguments as some + * hypervisors, e.g. Parallels Desktop, don't work when + * they are enqueued together. + */ struct { struct virtio_gpu_resource_attach_backing backing; - struct virtio_gpu_mem_entry mem[1]; + char pad; + struct virtio_gpu_mem_entry mem; } req; char pad; struct virtio_gpu_ctrl_hdr resp; @@ -577,11 +602,11 @@ vtgpu_attach_backing(struct vtgpu_softc *sc) s.req.backing.resource_id = htole32(VTGPU_RESOURCE_ID); s.req.backing.nr_entries = htole32(1); - s.req.mem[0].addr = htole64(sc->vtgpu_fb_info.fb_pbase); - s.req.mem[0].length = htole32(sc->vtgpu_fb_info.fb_size); + s.req.mem.addr = htole64(sc->vtgpu_fb_info.fb_pbase); + s.req.mem.length = htole32(sc->vtgpu_fb_info.fb_size); - error = vtgpu_req_resp(sc, &s.req, sizeof(s.req), &s.resp, - sizeof(s.resp)); + error = vtgpu_req_resp2(sc, &s.req.backing, sizeof(s.req.backing), + &s.req.mem, sizeof(s.req.mem), &s.resp, sizeof(s.resp)); if (error != 0) return (error); diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/if_vtnet.c index 19775416f8d4..40792482672c 100644 --- a/sys/dev/virtio/network/if_vtnet.c +++ b/sys/dev/virtio/network/if_vtnet.c @@ -96,6 +96,17 @@ #define VTNET_ETHER_ALIGN ETHER_ALIGN #endif +/* + * Worst case offset to ensure header doesn't share any cache lines with + * payload. + */ +#define VTNET_RX_BUFFER_HEADER_OFFSET 128 + +struct vtnet_rx_buffer_header { + bus_addr_t addr; + bus_dmamap_t dmap; +}; + static int vtnet_modevent(module_t, int, void *); static int vtnet_probe(device_t); @@ -135,7 +146,7 @@ static int vtnet_rxq_replace_buf(struct vtnet_rxq *, struct mbuf *, int); static int vtnet_rxq_enqueue_buf(struct vtnet_rxq *, struct mbuf *); static int vtnet_rxq_new_buf(struct vtnet_rxq *); #if defined(INET) || defined(INET6) -static int vtnet_rxq_csum_needs_csum(struct vtnet_rxq *, struct mbuf *, +static void vtnet_rxq_csum_needs_csum(struct vtnet_rxq *, struct mbuf *, bool, int, struct virtio_net_hdr *); static void vtnet_rxq_csum_data_valid(struct vtnet_rxq *, struct mbuf *, int); @@ -208,7 +219,7 @@ static void vtnet_init_locked(struct vtnet_softc *, int); static void vtnet_init(void *); static void vtnet_free_ctrl_vq(struct vtnet_softc *); -static void vtnet_exec_ctrl_cmd(struct vtnet_softc *, void *, +static int vtnet_exec_ctrl_cmd(struct vtnet_softc *, uint8_t *, struct sglist *, int, int); static int vtnet_ctrl_mac_cmd(struct vtnet_softc *, uint8_t *); static int vtnet_ctrl_guest_offloads(struct vtnet_softc *, uint64_t); @@ -273,11 +284,6 @@ static int vtnet_csum_disable = 0; SYSCTL_INT(_hw_vtnet, OID_AUTO, csum_disable, CTLFLAG_RDTUN, &vtnet_csum_disable, 0, "Disables receive and send checksum offload"); -static int vtnet_fixup_needs_csum = 0; -SYSCTL_INT(_hw_vtnet, OID_AUTO, fixup_needs_csum, CTLFLAG_RDTUN, - &vtnet_fixup_needs_csum, 0, - "Calculate valid checksum for NEEDS_CSUM packets"); - static int vtnet_tso_disable = 0; SYSCTL_INT(_hw_vtnet, OID_AUTO, tso_disable, CTLFLAG_RDTUN, &vtnet_tso_disable, 0, "Disables TSO"); @@ -389,6 +395,17 @@ MODULE_DEPEND(vtnet, netmap, 1, 1, 1); VIRTIO_SIMPLE_PNPINFO(vtnet, VIRTIO_ID_NETWORK, "VirtIO Networking Adapter"); +static struct vtnet_rx_buffer_header * +vtnet_mbuf_to_rx_buffer_header(struct vtnet_softc *sc, struct mbuf *m) +{ + if (VTNET_ETHER_ALIGN != 0 && sc->vtnet_hdr_size % 4 == 0) + return (struct vtnet_rx_buffer_header *)((uintptr_t)m->m_data - + VTNET_RX_BUFFER_HEADER_OFFSET - VTNET_ETHER_ALIGN); + else + return (struct vtnet_rx_buffer_header *)((uintptr_t)m->m_data - + VTNET_RX_BUFFER_HEADER_OFFSET); +} + static int vtnet_modevent(module_t mod __unused, int type, void *unused __unused) { @@ -462,6 +479,106 @@ vtnet_attach(device_t dev) goto fail; } + mtx_init(&sc->vtnet_rx_mtx, device_get_nameunit(dev), + "VirtIO Net RX lock", MTX_DEF); + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + sizeof(uint16_t), /* alignment */ + 0, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + MJUM9BYTES, /* max request size */ + 1, /* max # segments */ + MJUM9BYTES, /* maxsegsize - worst case */ + BUS_DMA_COHERENT, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &sc->vtnet_rx_mtx, /* lockarg */ + &sc->vtnet_rx_dmat); + if (error) { + device_printf(dev, "cannot create bus_dma_tag\n"); + goto fail; + } + + mtx_init(&sc->vtnet_tx_mtx, device_get_nameunit(dev), + "VirtIO Net TX lock", MTX_DEF); + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + sizeof(uint16_t), /* alignment */ + 0, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + sc->vtnet_tx_nsegs * MJUM9BYTES, /* max request size */ + sc->vtnet_tx_nsegs, /* max # segments */ + MJUM9BYTES, /* maxsegsize */ + BUS_DMA_COHERENT, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &sc->vtnet_tx_mtx, /* lockarg */ + &sc->vtnet_tx_dmat); + if (error) { + device_printf(dev, "cannot create bus_dma_tag\n"); + goto fail; + } + + mtx_init(&sc->vtnet_hdr_mtx, device_get_nameunit(dev), + "VirtIO Net header lock", MTX_DEF); + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + sizeof(uint16_t), /* alignment */ + 0, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + PAGE_SIZE, /* max request size */ + 1, /* max # segments */ + PAGE_SIZE, /* maxsegsize */ + BUS_DMA_COHERENT, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &sc->vtnet_hdr_mtx, /* lockarg */ + &sc->vtnet_hdr_dmat); + if (error) { + device_printf(dev, "cannot create bus_dma_tag\n"); + goto fail; + } + + mtx_init(&sc->vtnet_ack_mtx, device_get_nameunit(dev), + "VirtIO Net ACK lock", MTX_DEF); + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + sizeof(uint8_t), /* alignment */ + 0, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + sizeof(uint8_t), /* max request size */ + 1, /* max # segments */ + sizeof(uint8_t), /* maxsegsize */ + BUS_DMA_COHERENT, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &sc->vtnet_ack_mtx, /* lockarg */ + &sc->vtnet_ack_dmat); + if (error) { + device_printf(dev, "cannot create bus_dma_tag\n"); + goto fail; + } + +#ifdef __powerpc__ + /* + * Virtio uses physical addresses rather than bus addresses, so we + * need to ask busdma to skip the iommu physical->bus mapping. At + * present, this is only a thing on the powerpc architectures. + */ + bus_dma_tag_set_iommu(sc->vtnet_rx_dmat, NULL, NULL); + bus_dma_tag_set_iommu(sc->vtnet_tx_dmat, NULL, NULL); + bus_dma_tag_set_iommu(sc->vtnet_hdr_dmat, NULL, NULL); + bus_dma_tag_set_iommu(sc->vtnet_ack_dmat, NULL, NULL); +#endif + error = vtnet_alloc_rx_filters(sc); if (error) { device_printf(dev, "cannot allocate Rx filters\n"); @@ -1158,10 +1275,6 @@ vtnet_setup_interface(struct vtnet_softc *sc) if_setcapabilitiesbit(ifp, IFCAP_RXCSUM, 0); if_setcapabilitiesbit(ifp, IFCAP_RXCSUM_IPV6, 0); - if (vtnet_tunable_int(sc, "fixup_needs_csum", - vtnet_fixup_needs_csum) != 0) - sc->vtnet_flags |= VTNET_FLAG_FIXUP_NEEDS_CSUM; - /* Support either "hardware" or software LRO. */ if_setcapabilitiesbit(ifp, IFCAP_LRO, 0); } @@ -1554,6 +1667,11 @@ static struct mbuf * vtnet_rx_alloc_buf(struct vtnet_softc *sc, int nbufs, struct mbuf **m_tailp) { struct mbuf *m_head, *m_tail, *m; + struct vtnet_rx_buffer_header *vthdr; + bus_dma_segment_t segs[1]; + bus_dmamap_t dmap; + int nsegs; + int err; int i, size; m_head = NULL; @@ -1571,13 +1689,43 @@ vtnet_rx_alloc_buf(struct vtnet_softc *sc, int nbufs, struct mbuf **m_tailp) } m->m_len = size; + vthdr = (struct vtnet_rx_buffer_header *)m->m_data; + + /* Reserve space for header */ + m_adj(m, VTNET_RX_BUFFER_HEADER_OFFSET); + /* * Need to offset the mbuf if the header we're going to add * will misalign. */ - if (VTNET_ETHER_ALIGN != 0 && sc->vtnet_hdr_size % 4 == 0) { + if (VTNET_ETHER_ALIGN != 0 && sc->vtnet_hdr_size % 4 == 0) m_adj(m, VTNET_ETHER_ALIGN); + + err = bus_dmamap_create(sc->vtnet_rx_dmat, 0, &dmap); + if (err) { + printf("Failed to create dmamap, err :%d\n", + err); + m_freem(m); + return (NULL); } + + nsegs = 0; + err = bus_dmamap_load_mbuf_sg(sc->vtnet_rx_dmat, dmap, m, segs, + &nsegs, BUS_DMA_NOWAIT); + if (err != 0) { + printf("Failed to map mbuf into DMA visible memory, err: %d\n", + err); + m_freem(m); + bus_dmamap_destroy(sc->vtnet_rx_dmat, dmap); + return (NULL); + } + KASSERT(nsegs == 1, + ("%s: unexpected number of DMA segments for rx buffer: %d", + __func__, nsegs)); + + vthdr->addr = segs[0].ds_addr; + vthdr->dmap = dmap; + if (m_head != NULL) { m_tail->m_next = m; m_tail = m; @@ -1603,7 +1751,7 @@ vtnet_rxq_replace_lro_nomrg_buf(struct vtnet_rxq *rxq, struct mbuf *m0, int len, clustersz, nreplace, error; sc = rxq->vtnrx_sc; - clustersz = sc->vtnet_rx_clustersz; + clustersz = sc->vtnet_rx_clustersz - VTNET_RX_BUFFER_HEADER_OFFSET; /* * Need to offset the mbuf if the header we're going to add will * misalign, account for that here. @@ -1718,9 +1866,12 @@ vtnet_rxq_replace_buf(struct vtnet_rxq *rxq, struct mbuf *m, int len) static int vtnet_rxq_enqueue_buf(struct vtnet_rxq *rxq, struct mbuf *m) { + struct vtnet_rx_buffer_header *hdr; struct vtnet_softc *sc; struct sglist *sg; int header_inlined, error; + bus_addr_t paddr; + struct mbuf *mp; sc = rxq->vtnrx_sc; sg = rxq->vtnrx_sg; @@ -1733,28 +1884,38 @@ vtnet_rxq_enqueue_buf(struct vtnet_rxq *rxq, struct mbuf *m) header_inlined = vtnet_modern(sc) || (sc->vtnet_flags & VTNET_FLAG_MRG_RXBUFS) != 0; /* TODO: ANY_LAYOUT */ + hdr = vtnet_mbuf_to_rx_buffer_header(sc, m); + paddr = hdr->addr; + /* * Note: The mbuf has been already adjusted when we allocate it if we * have to do strict alignment. */ - if (header_inlined) - error = sglist_append_mbuf(sg, m); - else { - struct vtnet_rx_header *rxhdr = - mtod(m, struct vtnet_rx_header *); + if (header_inlined) { + error = sglist_append_phys(sg, paddr, m->m_len); + } else { MPASS(sc->vtnet_hdr_size == sizeof(struct virtio_net_hdr)); /* Append the header and remaining mbuf data. */ - error = sglist_append(sg, &rxhdr->vrh_hdr, sc->vtnet_hdr_size); + error = sglist_append_phys(sg, paddr, sc->vtnet_hdr_size); if (error) return (error); - error = sglist_append(sg, &rxhdr[1], + error = sglist_append_phys(sg, + paddr + sizeof(struct vtnet_rx_header), m->m_len - sizeof(struct vtnet_rx_header)); if (error) return (error); - if (m->m_next != NULL) - error = sglist_append_mbuf(sg, m->m_next); + mp = m->m_next; + while (mp) { + hdr = vtnet_mbuf_to_rx_buffer_header(sc, mp); + paddr = hdr->addr; + error = sglist_append_phys(sg, paddr, mp->m_len); + if (error) + return (error); + + mp = mp->m_next; + } } if (error) @@ -1784,12 +1945,10 @@ vtnet_rxq_new_buf(struct vtnet_rxq *rxq) } #if defined(INET) || defined(INET6) -static int +static void vtnet_rxq_csum_needs_csum(struct vtnet_rxq *rxq, struct mbuf *m, bool isipv6, int protocol, struct virtio_net_hdr *hdr) { - struct vtnet_softc *sc; - /* * The packet is likely from another VM on the same host or from the * host that itself performed checksum offloading so Tx/Rx is basically @@ -1800,57 +1959,18 @@ vtnet_rxq_csum_needs_csum(struct vtnet_rxq *rxq, struct mbuf *m, bool isipv6, ("%s: unsupported IP protocol %d", __func__, protocol)); /* - * If the user don't want us to fix it up here by computing the - * checksum, just forward the order to compute the checksum by setting + * Just forward the order to compute the checksum by setting * the corresponding mbuf flag (e.g., CSUM_TCP). */ - sc = rxq->vtnrx_sc; - if ((sc->vtnet_flags & VTNET_FLAG_FIXUP_NEEDS_CSUM) == 0) { - switch (protocol) { - case IPPROTO_TCP: - m->m_pkthdr.csum_flags |= - (isipv6 ? CSUM_TCP_IPV6 : CSUM_TCP); - break; - case IPPROTO_UDP: - m->m_pkthdr.csum_flags |= - (isipv6 ? CSUM_UDP_IPV6 : CSUM_UDP); - break; - } - m->m_pkthdr.csum_data = hdr->csum_offset; - return (0); - } - - /* - * Compute the checksum in the driver so the packet will contain a - * valid checksum. The checksum is at csum_offset from csum_start. - */ - int csum_off, csum_end; - uint16_t csum; - - csum_off = hdr->csum_start + hdr->csum_offset; - csum_end = csum_off + sizeof(uint16_t); - - /* Assume checksum will be in the first mbuf. */ - if (m->m_len < csum_end || m->m_pkthdr.len < csum_end) { - sc->vtnet_stats.rx_csum_bad_offset++; - return (1); + switch (protocol) { + case IPPROTO_TCP: + m->m_pkthdr.csum_flags |= (isipv6 ? CSUM_TCP_IPV6 : CSUM_TCP); + break; + case IPPROTO_UDP: + m->m_pkthdr.csum_flags |= (isipv6 ? CSUM_UDP_IPV6 : CSUM_UDP); + break; } - - /* - * Like in_delayed_cksum()/in6_delayed_cksum(), compute the - * checksum and write it at the specified offset. We could - * try to verify the packet: csum_start should probably - * correspond to the start of the TCP/UDP header. - * - * BMV: Need to properly handle UDP with zero checksum. Is - * the IPv4 header checksum implicitly validated? - */ - csum = in_cksum_skip(m, m->m_pkthdr.len, hdr->csum_start); - *(uint16_t *)(mtodo(m, csum_off)) = csum; - m->m_pkthdr.csum_flags |= CSUM_DATA_VALID | CSUM_PSEUDO_HDR; - m->m_pkthdr.csum_data = 0xFFFF; - - return (0); + m->m_pkthdr.csum_data = hdr->csum_offset; } static void @@ -1934,8 +2054,7 @@ vtnet_rxq_csum(struct vtnet_rxq *rxq, struct mbuf *m, } if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) - return (vtnet_rxq_csum_needs_csum(rxq, m, isipv6, protocol, - hdr)); + vtnet_rxq_csum_needs_csum(rxq, m, isipv6, protocol, hdr); else /* VIRTIO_NET_HDR_F_DATA_VALID */ vtnet_rxq_csum_data_valid(rxq, m, protocol); @@ -1982,6 +2101,7 @@ vtnet_rxq_merged_eof(struct vtnet_rxq *rxq, struct mbuf *m_head, int nbufs) m_tail = m_head; while (--nbufs > 0) { + struct vtnet_rx_buffer_header *vthdr; struct mbuf *m; uint32_t len; @@ -1991,6 +2111,10 @@ vtnet_rxq_merged_eof(struct vtnet_rxq *rxq, struct mbuf *m_head, int nbufs) goto fail; } + vthdr = vtnet_mbuf_to_rx_buffer_header(sc, m); + bus_dmamap_sync(sc->vtnet_rx_dmat, vthdr->dmap, + BUS_DMASYNC_POSTREAD); + if (vtnet_rxq_new_buf(rxq) != 0) { rxq->vtnrx_stats.vrxs_iqdrops++; vtnet_rxq_discard_buf(rxq, m); @@ -2059,8 +2183,16 @@ vtnet_rxq_input(struct vtnet_rxq *rxq, struct mbuf *m, } } - m->m_pkthdr.flowid = rxq->vtnrx_id; - M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE); + if (sc->vtnet_act_vq_pairs == 1) { + /* + * When RSS is not needed (one active rx queue), let the upper + * layer know and react. + */ + M_HASHTYPE_CLEAR(m); + } else { + m->m_pkthdr.flowid = rxq->vtnrx_id; + M_HASHTYPE_SET(m, M_HASHTYPE_OPAQUE); + } if (hdr->flags & (VIRTIO_NET_HDR_F_NEEDS_CSUM | VIRTIO_NET_HDR_F_DATA_VALID)) { @@ -2103,6 +2235,7 @@ static int vtnet_rxq_eof(struct vtnet_rxq *rxq) { struct virtio_net_hdr lhdr, *hdr; + struct vtnet_rx_buffer_header *vthdr; struct vtnet_softc *sc; if_t ifp; struct virtqueue *vq; @@ -2118,14 +2251,31 @@ vtnet_rxq_eof(struct vtnet_rxq *rxq) CURVNET_SET(if_getvnet(ifp)); while (count-- > 0) { - struct mbuf *m; + struct mbuf *m, *mp; uint32_t len, nbufs, adjsz; + uint32_t synced; m = virtqueue_dequeue(vq, &len); if (m == NULL) break; deq++; + mp = m; + + /* + * Sync all mbufs in this packet. There will only be a single + * mbuf unless LRO is in use. + */ + synced = 0; + while (mp && synced < len) { + vthdr = vtnet_mbuf_to_rx_buffer_header(sc, mp); + bus_dmamap_sync(sc->vtnet_rx_dmat, vthdr->dmap, + BUS_DMASYNC_POSTREAD); + + synced += mp->m_len; + mp = mp->m_next; + } + if (len < sc->vtnet_hdr_size + ETHER_HDR_LEN) { rxq->vtnrx_stats.vrxs_ierrors++; vtnet_rxq_discard_buf(rxq, m); @@ -2385,6 +2535,14 @@ vtnet_txq_free_mbufs(struct vtnet_txq *txq) while ((txhdr = virtqueue_drain(vq, &last)) != NULL) { if (kring == NULL) { + bus_dmamap_unload(txq->vtntx_sc->vtnet_tx_dmat, + txhdr->dmap); + bus_dmamap_destroy(txq->vtntx_sc->vtnet_tx_dmat, + txhdr->dmap); + bus_dmamap_unload(txq->vtntx_sc->vtnet_tx_dmat, + txhdr->hdr_dmap); + bus_dmamap_destroy(txq->vtntx_sc->vtnet_tx_dmat, + txhdr->hdr_dmap); m_freem(txhdr->vth_mbuf); uma_zfree(vtnet_tx_header_zone, txhdr); } @@ -2554,15 +2712,36 @@ drop: return (NULL); } +static void +vtnet_txq_enqueue_callback(void *arg, bus_dma_segment_t *segs, + int nsegs, int error) +{ + vm_paddr_t *hdr_paddr; + + if (error != 0) + return; + + KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); + + hdr_paddr = (vm_paddr_t *)arg; + *hdr_paddr = segs[0].ds_addr; +} + static int vtnet_txq_enqueue_buf(struct vtnet_txq *txq, struct mbuf **m_head, struct vtnet_tx_header *txhdr) { + bus_dma_segment_t segs[VTNET_TX_SEGS_MAX]; + int nsegs; struct vtnet_softc *sc; struct virtqueue *vq; struct sglist *sg; struct mbuf *m; int error; + vm_paddr_t hdr_paddr; + bus_dmamap_t hdr_dmap; + bus_dmamap_t dmap; + int i; sc = txq->vtntx_sc; vq = txq->vtntx_vq; @@ -2570,15 +2749,55 @@ vtnet_txq_enqueue_buf(struct vtnet_txq *txq, struct mbuf **m_head, m = *m_head; sglist_reset(sg); - error = sglist_append(sg, &txhdr->vth_uhdr, sc->vtnet_hdr_size); + + error = bus_dmamap_create(sc->vtnet_tx_dmat, 0, &hdr_dmap); + if (error) + goto fail; + + error = bus_dmamap_load(sc->vtnet_tx_dmat, hdr_dmap, &txhdr->vth_uhdr, + sc->vtnet_hdr_size, vtnet_txq_enqueue_callback, &hdr_paddr, + BUS_DMA_NOWAIT); + if (error) + goto fail_hdr_dmamap_destroy; + + error = sglist_append_phys(sg, hdr_paddr, sc->vtnet_hdr_size); if (error != 0 || sg->sg_nseg != 1) { KASSERT(0, ("%s: cannot add header to sglist error %d nseg %d", __func__, error, sg->sg_nseg)); - goto fail; + goto fail_hdr_dmamap_unload; } - error = sglist_append_mbuf(sg, m); + bus_dmamap_sync(sc->vtnet_tx_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); + + error = bus_dmamap_create(sc->vtnet_tx_dmat, 0, &dmap); + if (error) + goto fail_hdr_dmamap_unload; + + nsegs = 0; + error = bus_dmamap_load_mbuf_sg(sc->vtnet_tx_dmat, dmap, m, segs, + &nsegs, BUS_DMA_NOWAIT); + if (error != 0) + goto fail_dmamap_destroy; + KASSERT(nsegs <= sc->vtnet_tx_nsegs, + ("%s: unexpected number of DMA segments for tx buffer: %d (max %d)", + __func__, nsegs, sc->vtnet_tx_nsegs)); + + bus_dmamap_sync(sc->vtnet_tx_dmat, dmap, BUS_DMASYNC_PREWRITE); + + for (i = 0; i < nsegs && !error; i++) + error = sglist_append_phys(sg, segs[i].ds_addr, segs[i].ds_len); + if (error) { + sglist_reset(sg); + bus_dmamap_unload(sc->vtnet_tx_dmat, dmap); + + error = sglist_append_phys(sg, hdr_paddr, sc->vtnet_hdr_size); + if (error != 0 || sg->sg_nseg != 1) { + KASSERT(0, ("%s: cannot add header to sglist error %d nseg %d", + __func__, error, sg->sg_nseg)); + goto fail_dmamap_destroy; + } + m = m_defrag(m, M_NOWAIT); if (m == NULL) { sc->vtnet_stats.tx_defrag_failed++; @@ -2588,16 +2807,41 @@ vtnet_txq_enqueue_buf(struct vtnet_txq *txq, struct mbuf **m_head, *m_head = m; sc->vtnet_stats.tx_defragged++; - error = sglist_append_mbuf(sg, m); + nsegs = 0; + error = bus_dmamap_load_mbuf_sg(sc->vtnet_tx_dmat, dmap, m, + segs, &nsegs, BUS_DMA_NOWAIT); + if (error != 0) + goto fail_dmamap_destroy; + KASSERT(nsegs <= sc->vtnet_tx_nsegs, + ("%s: unexpected number of DMA segments for tx buffer: %d (max %d)", + __func__, nsegs, sc->vtnet_tx_nsegs)); + + bus_dmamap_sync(sc->vtnet_tx_dmat, dmap, BUS_DMASYNC_PREWRITE); + + for (i = 0; i < nsegs && !error; i++) + error = sglist_append_phys(sg, segs[i].ds_addr, + segs[i].ds_len); + if (error) - goto fail; + goto fail_dmamap_unload; } txhdr->vth_mbuf = m; + txhdr->dmap = dmap; + txhdr->hdr_dmap = hdr_dmap; + error = virtqueue_enqueue(vq, txhdr, sg, sg->sg_nseg, 0); return (error); +fail_dmamap_unload: + bus_dmamap_unload(sc->vtnet_tx_dmat, dmap); +fail_dmamap_destroy: + bus_dmamap_destroy(sc->vtnet_tx_dmat, dmap); +fail_hdr_dmamap_unload: + bus_dmamap_unload(sc->vtnet_tx_dmat, hdr_dmap); +fail_hdr_dmamap_destroy: + bus_dmamap_destroy(sc->vtnet_tx_dmat, hdr_dmap); fail: m_freem(*m_head); *m_head = NULL; @@ -3553,10 +3797,43 @@ vtnet_free_ctrl_vq(struct vtnet_softc *sc) } static void -vtnet_exec_ctrl_cmd(struct vtnet_softc *sc, void *cookie, - struct sglist *sg, int readable, int writable) +vtnet_load_callback(void *arg, bus_dma_segment_t *segs, int nsegs, + int error) { + bus_addr_t *paddr; + + if (error != 0) + return; + + KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); + + paddr = (bus_addr_t *)arg; + *paddr = segs[0].ds_addr; +} + +static int +vtnet_exec_ctrl_cmd(struct vtnet_softc *sc, uint8_t *ack, struct sglist *sg, + int readable, int writable) +{ + bus_dmamap_t ack_dmap; + bus_addr_t ack_paddr; struct virtqueue *vq; + int error; + + error = bus_dmamap_create(sc->vtnet_ack_dmat, 0, &ack_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_ack_dmat, ack_dmap, ack, + sizeof(uint8_t), vtnet_load_callback, &ack_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy; + + bus_dmamap_sync(sc->vtnet_ack_dmat, ack_dmap, BUS_DMASYNC_PREWRITE); + + error = sglist_append_phys(sg, ack_paddr, sizeof(uint8_t)); + if (error) + goto error_unload; vq = sc->vtnet_ctrl_vq; @@ -3564,152 +3841,237 @@ vtnet_exec_ctrl_cmd(struct vtnet_softc *sc, void *cookie, VTNET_CORE_LOCK_ASSERT(sc); if (!virtqueue_empty(vq)) - return; + goto error_unload; /* * Poll for the response, but the command is likely completed before * returning from the notify. */ - if (virtqueue_enqueue(vq, cookie, sg, readable, writable) == 0) { + if (virtqueue_enqueue(vq, (void *)ack, sg, readable, writable) == 0) { virtqueue_notify(vq); virtqueue_poll(vq, NULL); } + + bus_dmamap_sync(sc->vtnet_ack_dmat, ack_dmap, BUS_DMASYNC_POSTREAD); + +error_unload: + bus_dmamap_unload(sc->vtnet_ack_dmat, ack_dmap); +error_destroy: + bus_dmamap_destroy(sc->vtnet_ack_dmat, ack_dmap); +error_out: + return (error); } static int vtnet_ctrl_mac_cmd(struct vtnet_softc *sc, uint8_t *hwaddr) { struct sglist_seg segs[3]; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; struct { struct virtio_net_ctrl_hdr hdr __aligned(2); uint8_t pad1; uint8_t addr[ETHER_ADDR_LEN] __aligned(8); uint8_t pad2; - uint8_t ack; } s; + uint8_t ack; int error; - error = 0; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s, + sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy_hdr; + MPASS(sc->vtnet_flags & VTNET_FLAG_CTRL_MAC); s.hdr.class = VIRTIO_NET_CTRL_MAC; s.hdr.cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET; bcopy(hwaddr, &s.addr[0], ETHER_ADDR_LEN); - s.ack = VIRTIO_NET_ERR; + ack = VIRTIO_NET_ERR; + bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &s.addr[0], ETHER_ADDR_LEN); - error |= sglist_append(&sg, &s.ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + hdr_paddr + ((uintptr_t)&s.addr - (uintptr_t)&s), + ETHER_ADDR_LEN); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1); + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); - return (s.ack == VIRTIO_NET_OK ? 0 : EIO); + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +error_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +error_out: + return (error); } static int vtnet_ctrl_guest_offloads(struct vtnet_softc *sc, uint64_t offloads) { struct sglist_seg segs[3]; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; struct { struct virtio_net_ctrl_hdr hdr __aligned(2); uint8_t pad1; uint64_t offloads __aligned(8); uint8_t pad2; - uint8_t ack; } s; + uint8_t ack; int error; - error = 0; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s, + sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy_hdr; + MPASS(sc->vtnet_features & VIRTIO_NET_F_CTRL_GUEST_OFFLOADS); s.hdr.class = VIRTIO_NET_CTRL_GUEST_OFFLOADS; s.hdr.cmd = VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET; s.offloads = vtnet_gtoh64(sc, offloads); - s.ack = VIRTIO_NET_ERR; + ack = VIRTIO_NET_ERR; + bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &s.offloads, sizeof(uint64_t)); - error |= sglist_append(&sg, &s.ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + hdr_paddr + ((uintptr_t)&s.offloads - (uintptr_t)&s), + sizeof(uint64_t)); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1); + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); - return (s.ack == VIRTIO_NET_OK ? 0 : EIO); + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +error_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +error_out: + return (error); } static int vtnet_ctrl_mq_cmd(struct vtnet_softc *sc, uint16_t npairs) { struct sglist_seg segs[3]; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; struct { struct virtio_net_ctrl_hdr hdr __aligned(2); uint8_t pad1; struct virtio_net_ctrl_mq mq __aligned(2); uint8_t pad2; - uint8_t ack; } s; + uint8_t ack; int error; - error = 0; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s, + sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy_hdr; + MPASS(sc->vtnet_flags & VTNET_FLAG_MQ); s.hdr.class = VIRTIO_NET_CTRL_MQ; s.hdr.cmd = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET; s.mq.virtqueue_pairs = vtnet_gtoh16(sc, npairs); - s.ack = VIRTIO_NET_ERR; + ack = VIRTIO_NET_ERR; + bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &s.mq, sizeof(struct virtio_net_ctrl_mq)); - error |= sglist_append(&sg, &s.ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + hdr_paddr + ((uintptr_t)&s.mq - (uintptr_t)&s), + sizeof(struct virtio_net_ctrl_mq)); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1); + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); - return (s.ack == VIRTIO_NET_OK ? 0 : EIO); + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +error_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +error_out: + return (error); } static int vtnet_ctrl_rx_cmd(struct vtnet_softc *sc, uint8_t cmd, bool on) { struct sglist_seg segs[3]; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; struct { struct virtio_net_ctrl_hdr hdr __aligned(2); uint8_t pad1; uint8_t onoff; uint8_t pad2; - uint8_t ack; } s; + uint8_t ack; int error; - error = 0; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s, + sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy_hdr; + MPASS(sc->vtnet_flags & VTNET_FLAG_CTRL_RX); s.hdr.class = VIRTIO_NET_CTRL_RX; s.hdr.cmd = cmd; s.onoff = on; - s.ack = VIRTIO_NET_ERR; + ack = VIRTIO_NET_ERR; + bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &s.onoff, sizeof(uint8_t)); - error |= sglist_append(&sg, &s.ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + hdr_paddr + ((uintptr_t)&s.onoff - (uintptr_t)&s), + sizeof(uint8_t)); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1); + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); - return (s.ack == VIRTIO_NET_OK ? 0 : EIO); + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +error_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +error_out: + return (error); } static int @@ -3780,6 +4142,10 @@ vtnet_rx_filter_mac(struct vtnet_softc *sc) struct virtio_net_ctrl_hdr hdr __aligned(2); struct vtnet_mac_filter *filter; struct sglist_seg segs[4]; + bus_dmamap_t filter_dmap; + bus_addr_t filter_paddr; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; if_t ifp; bool promisc, allmulti; @@ -3819,6 +4185,25 @@ vtnet_rx_filter_mac(struct vtnet_softc *sc) if (promisc && allmulti) goto out; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto out_error; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &hdr, + sizeof(hdr), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto out_destroy_hdr; + + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &filter_dmap); + if (error) + goto out_unload_hdr; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, filter, + sizeof(*filter), vtnet_load_callback, &filter_paddr, + BUS_DMA_NOWAIT); + if (error) + goto out_destroy_filter; + filter->vmf_unicast.nentries = vtnet_gtoh32(sc, ucnt); filter->vmf_multicast.nentries = vtnet_gtoh32(sc, mcnt); @@ -3827,19 +4212,33 @@ vtnet_rx_filter_mac(struct vtnet_softc *sc) ack = VIRTIO_NET_ERR; sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &filter->vmf_unicast, + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + filter_paddr + ((uintptr_t)&filter->vmf_unicast - + (uintptr_t)filter), sizeof(uint32_t) + ucnt * ETHER_ADDR_LEN); - error |= sglist_append(&sg, &filter->vmf_multicast, + error |= sglist_append_phys(&sg, + filter_paddr + ((uintptr_t)&filter->vmf_multicast - + (uintptr_t)filter), sizeof(uint32_t) + mcnt * ETHER_ADDR_LEN); - error |= sglist_append(&sg, &ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg - 1, 1); - if (ack != VIRTIO_NET_OK) + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); + + bus_dmamap_unload(sc->vtnet_hdr_dmat, filter_dmap); +out_destroy_filter: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, filter_dmap); +out_unload_hdr: + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +out_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +out_error: + if (error != 0) if_printf(ifp, "error setting host MAC filter table\n"); - out: if (promisc && vtnet_set_promisc(sc, true) != 0) if_printf(ifp, "cannot enable promiscuous mode\n"); @@ -3851,34 +4250,53 @@ static int vtnet_exec_vlan_filter(struct vtnet_softc *sc, int add, uint16_t tag) { struct sglist_seg segs[3]; + bus_dmamap_t hdr_dmap; + bus_addr_t hdr_paddr; struct sglist sg; struct { struct virtio_net_ctrl_hdr hdr __aligned(2); uint8_t pad1; uint16_t tag __aligned(2); uint8_t pad2; - uint8_t ack; } s; + uint8_t ack; int error; - error = 0; + error = bus_dmamap_create(sc->vtnet_hdr_dmat, 0, &hdr_dmap); + if (error) + goto error_out; + + error = bus_dmamap_load(sc->vtnet_hdr_dmat, hdr_dmap, &s, + sizeof(s), vtnet_load_callback, &hdr_paddr, BUS_DMA_NOWAIT); + if (error) + goto error_destroy_hdr; + MPASS(sc->vtnet_flags & VTNET_FLAG_VLAN_FILTER); s.hdr.class = VIRTIO_NET_CTRL_VLAN; s.hdr.cmd = add ? VIRTIO_NET_CTRL_VLAN_ADD : VIRTIO_NET_CTRL_VLAN_DEL; s.tag = vtnet_gtoh16(sc, tag); - s.ack = VIRTIO_NET_ERR; + ack = VIRTIO_NET_ERR; + bus_dmamap_sync(sc->vtnet_hdr_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE); sglist_init(&sg, nitems(segs), segs); - error |= sglist_append(&sg, &s.hdr, sizeof(struct virtio_net_ctrl_hdr)); - error |= sglist_append(&sg, &s.tag, sizeof(uint16_t)); - error |= sglist_append(&sg, &s.ack, sizeof(uint8_t)); - MPASS(error == 0 && sg.sg_nseg == nitems(segs)); + error |= sglist_append_phys(&sg, hdr_paddr, + sizeof(struct virtio_net_ctrl_hdr)); + error |= sglist_append_phys(&sg, + hdr_paddr + ((uintptr_t)&s.tag - (uintptr_t)&s), + sizeof(uint16_t)); + MPASS(error == 0 && sg.sg_nseg == nitems(segs) - 1); if (error == 0) - vtnet_exec_ctrl_cmd(sc, &s.ack, &sg, sg.sg_nseg - 1, 1); + error = vtnet_exec_ctrl_cmd(sc, &ack, &sg, sg.sg_nseg, 1); + if (error == 0) + error = (ack == VIRTIO_NET_OK ? 0 : EIO); - return (s.ack == VIRTIO_NET_OK ? 0 : EIO); + bus_dmamap_unload(sc->vtnet_hdr_dmat, hdr_dmap); +error_destroy_hdr: + bus_dmamap_destroy(sc->vtnet_hdr_dmat, hdr_dmap); +error_out: + return (error); } static void @@ -4346,9 +4764,6 @@ vtnet_setup_stat_sysctl(struct sysctl_ctx_list *ctx, SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_csum_bad_ipproto", CTLFLAG_RD | CTLFLAG_STATS, &stats->rx_csum_bad_ipproto, "Received checksum offloaded buffer with incorrect IP protocol"); - SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_csum_bad_offset", - CTLFLAG_RD | CTLFLAG_STATS, &stats->rx_csum_bad_offset, - "Received checksum offloaded buffer with incorrect offset"); SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "rx_csum_inaccessible_ipproto", CTLFLAG_RD | CTLFLAG_STATS, &stats->rx_csum_inaccessible_ipproto, "Received checksum offloaded buffer with inaccessible IP protocol"); diff --git a/sys/dev/virtio/network/if_vtnetvar.h b/sys/dev/virtio/network/if_vtnetvar.h index eb5e6784b07f..e445bdf6d6cb 100644 --- a/sys/dev/virtio/network/if_vtnetvar.h +++ b/sys/dev/virtio/network/if_vtnetvar.h @@ -190,6 +190,18 @@ struct vtnet_softc { struct mtx vtnet_mtx; char vtnet_mtx_name[16]; uint8_t vtnet_hwaddr[ETHER_ADDR_LEN]; + + bus_dma_tag_t vtnet_rx_dmat; + struct mtx vtnet_rx_mtx; + + bus_dma_tag_t vtnet_tx_dmat; + struct mtx vtnet_tx_mtx; + + bus_dma_tag_t vtnet_hdr_dmat; + struct mtx vtnet_hdr_mtx; + + bus_dma_tag_t vtnet_ack_dmat; + struct mtx vtnet_ack_mtx; }; /* vtnet flag descriptions for use with printf(9) %b identifier. */ #define VTNET_FLAGS_BITS \ @@ -273,6 +285,10 @@ struct vtnet_tx_header { } vth_uhdr; struct mbuf *vth_mbuf; + + bus_dmamap_t dmap; + + bus_dmamap_t hdr_dmap; }; /* diff --git a/sys/dev/virtio/p9fs/virtio_p9fs.c b/sys/dev/virtio/p9fs/virtio_p9fs.c index aa84d3970698..2b276a60aa9a 100644 --- a/sys/dev/virtio/p9fs/virtio_p9fs.c +++ b/sys/dev/virtio/p9fs/virtio_p9fs.c @@ -84,6 +84,8 @@ static struct virtio_feature_desc virtio_9p_feature_desc[] = { { 0, NULL } }; +VIRTIO_SIMPLE_PNPINFO(virtio_p9fs, VIRTIO_ID_9P, "VirtIO 9P Transport"); + /* We don't currently allow canceling of virtio requests */ static int vt9p_cancel(void *handle, struct p9_req_t *req) @@ -257,13 +259,7 @@ vt9p_alloc_virtqueue(struct vt9p_softc *sc) static int vt9p_probe(device_t dev) { - - /* If the virtio device type is a 9P device, then we claim and attach it */ - if (virtio_get_device_type(dev) != VIRTIO_ID_9P) - return (ENXIO); - device_set_desc(dev, "VirtIO 9P Transport"); - - return (BUS_PROBE_DEFAULT); + return (VIRTIO_SIMPLE_PROBE(dev, virtio_p9fs)); } static void diff --git a/sys/dev/virtio/pci/virtio_pci.c b/sys/dev/virtio/pci/virtio_pci.c index b7b34b448f6e..2d33d99014ae 100644 --- a/sys/dev/virtio/pci/virtio_pci.c +++ b/sys/dev/virtio/pci/virtio_pci.c @@ -97,8 +97,13 @@ MODULE_VERSION(virtio_pci, 1); MODULE_DEPEND(virtio_pci, pci, 1, 1, 1); MODULE_DEPEND(virtio_pci, virtio, 1, 1, 1); +SYSCTL_DECL(_hw_virtio); +SYSCTL_NODE(_hw_virtio, OID_AUTO, pci, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, + "VirtIO PCI driver parameters"); + int vtpci_disable_msix = 0; -TUNABLE_INT("hw.virtio.pci.disable_msix", &vtpci_disable_msix); +SYSCTL_INT(_hw_virtio_pci, OID_AUTO, disable_msix, CTLFLAG_RDTUN, + &vtpci_disable_msix, 0, "If set to 1, disables MSI-X."); static uint8_t vtpci_read_isr(struct vtpci_common *cn) diff --git a/sys/dev/virtio/pci/virtio_pci_modern.c b/sys/dev/virtio/pci/virtio_pci_modern.c index eb1d5a1e6989..baf7c448bb95 100644 --- a/sys/dev/virtio/pci/virtio_pci_modern.c +++ b/sys/dev/virtio/pci/virtio_pci_modern.c @@ -33,6 +33,7 @@ #include <sys/bus.h> #include <sys/lock.h> #include <sys/kernel.h> +#include <sys/sysctl.h> #include <sys/module.h> #include <machine/bus.h> @@ -188,8 +189,12 @@ static void vtpci_modern_write_device_8(struct vtpci_modern_softc *, bus_size_t, uint64_t); /* Tunables. */ -static int vtpci_modern_transitional = 0; -TUNABLE_INT("hw.virtio.pci.transitional", &vtpci_modern_transitional); +SYSCTL_DECL(_hw_virtio_pci); + +static int vtpci_modern_transitional = 1; +SYSCTL_INT(_hw_virtio_pci, OID_AUTO, transitional, CTLFLAG_RDTUN, + &vtpci_modern_transitional, 0, + "If 0, a transitional VirtIO device is used in legacy mode; otherwise, in modern mode."); static device_method_t vtpci_modern_methods[] = { /* Device interface. */ diff --git a/sys/dev/virtio/virtio.c b/sys/dev/virtio/virtio.c index 75d65ba4a8c8..be5edcafa7ff 100644 --- a/sys/dev/virtio/virtio.c +++ b/sys/dev/virtio/virtio.c @@ -30,6 +30,7 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <sys/sysctl.h> #include <sys/module.h> #include <sys/sbuf.h> @@ -90,6 +91,9 @@ static struct virtio_feature_desc virtio_common_feature_desc[] = { { 0, NULL } }; +SYSCTL_NODE(_hw, OID_AUTO, virtio, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, + "VirtIO driver parameters"); + const char * virtio_device_name(uint16_t devid) { diff --git a/sys/dev/virtio/virtio.h b/sys/dev/virtio/virtio.h index 855dafd63033..1b8dc630e339 100644 --- a/sys/dev/virtio/virtio.h +++ b/sys/dev/virtio/virtio.h @@ -53,13 +53,15 @@ struct vq_alloc_info; /* * VirtIO instance variables indices. */ -#define VIRTIO_IVAR_DEVTYPE 1 -#define VIRTIO_IVAR_FEATURE_DESC 2 -#define VIRTIO_IVAR_VENDOR 3 -#define VIRTIO_IVAR_DEVICE 4 -#define VIRTIO_IVAR_SUBVENDOR 5 -#define VIRTIO_IVAR_SUBDEVICE 6 -#define VIRTIO_IVAR_MODERN 7 +enum { + VIRTIO_IVAR_DEVTYPE = BUS_IVARS_PRIVATE, + VIRTIO_IVAR_FEATURE_DESC, + VIRTIO_IVAR_VENDOR, + VIRTIO_IVAR_DEVICE, + VIRTIO_IVAR_SUBVENDOR, + VIRTIO_IVAR_SUBDEVICE, + VIRTIO_IVAR_MODERN +}; struct virtio_feature_desc { uint64_t vfd_val; diff --git a/sys/dev/virtio/virtio_ring.h b/sys/dev/virtio/virtio_ring.h index 15348a77d8a3..7ac78f0defed 100644 --- a/sys/dev/virtio/virtio_ring.h +++ b/sys/dev/virtio/virtio_ring.h @@ -88,6 +88,10 @@ struct vring { struct vring_desc *desc; struct vring_avail *avail; struct vring_used *used; + + vm_paddr_t desc_paddr; + vm_paddr_t avail_paddr; + vm_paddr_t used_paddr; }; /* Alignment requirements for vring elements. @@ -145,15 +149,24 @@ vring_size(unsigned int num, unsigned long align) } static inline void -vring_init(struct vring *vr, unsigned int num, uint8_t *p, +vring_init(struct vring *vr, unsigned int num, uint8_t *p, vm_paddr_t paddr, unsigned long align) { - vr->num = num; - vr->desc = (struct vring_desc *) p; - vr->avail = (struct vring_avail *) (p + - num * sizeof(struct vring_desc)); - vr->used = (void *) - (((unsigned long) &vr->avail->ring[num] + align-1) & ~(align-1)); + unsigned long avail_offset; + unsigned long used_offset; + + avail_offset = num * sizeof(struct vring_desc); + used_offset = (avail_offset + sizeof(struct vring_avail) + + sizeof(uint16_t) * num + align - 1) & ~(align - 1); + + vr->num = num; + vr->desc = (struct vring_desc *) p; + vr->avail = (struct vring_avail *) (p + avail_offset); + vr->used = (struct vring_used *) (p + used_offset); + + vr->desc_paddr = paddr; + vr->avail_paddr = paddr + avail_offset; + vr->used_paddr = paddr + used_offset; } /* diff --git a/sys/dev/virtio/virtqueue.c b/sys/dev/virtio/virtqueue.c index 41e01549c8b2..10b5179bd3d5 100644 --- a/sys/dev/virtio/virtqueue.c +++ b/sys/dev/virtio/virtqueue.c @@ -35,6 +35,7 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <sys/mutex.h> #include <sys/sdt.h> #include <sys/sglist.h> #include <vm/vm.h> @@ -55,6 +56,8 @@ struct virtqueue { device_t vq_dev; + struct mtx vq_ring_mtx; + struct mtx vq_indirect_mtx; uint16_t vq_queue_index; uint16_t vq_nentries; uint32_t vq_flags; @@ -83,15 +86,22 @@ struct virtqueue { uint16_t vq_used_cons_idx; void *vq_ring_mem; + bus_dmamap_t vq_ring_mapp; + vm_paddr_t vq_ring_paddr; + int vq_indirect_mem_size; int vq_alignment; int vq_ring_size; char vq_name[VIRTQUEUE_MAX_NAME_SZ]; + bus_dma_tag_t vq_ring_dmat; + bus_dma_tag_t vq_indirect_dmat; + struct vq_desc_extra { void *cookie; struct vring_desc *indirect; vm_paddr_t indirect_paddr; + bus_dmamap_t mapp; uint16_t ndescs; } vq_descx[0]; }; @@ -148,6 +158,21 @@ SDT_PROBE_DEFINE1(virtqueue, , enqueue_segments, return, "uint16_t"); #define vq_gtoh32(_vq, _val) virtio_gtoh32(vq_modern(_vq), _val) #define vq_gtoh64(_vq, _val) virtio_gtoh64(vq_modern(_vq), _val) +static void +virtqueue_ring_load_callback(void *arg, bus_dma_segment_t *segs, + int nsegs, int error) +{ + struct virtqueue *vq; + + if (error != 0) + return; + + KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); + + vq = (struct virtqueue *)arg; + vq->vq_ring_paddr = segs[0].ds_addr; +} + int virtqueue_alloc(device_t dev, uint16_t queue, uint16_t size, bus_size_t notify_offset, int align, vm_paddr_t highaddr, @@ -199,19 +224,58 @@ virtqueue_alloc(device_t dev, uint16_t queue, uint16_t size, if (VIRTIO_BUS_WITH_FEATURE(dev, VIRTIO_RING_F_EVENT_IDX) != 0) vq->vq_flags |= VIRTQUEUE_FLAG_EVENT_IDX; + vq->vq_ring_size = round_page(vring_size(size, align)); + + mtx_init(&vq->vq_ring_mtx, device_get_nameunit(dev), + "VirtIO Queue Lock", MTX_DEF); + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + align, /* alignment */ + 0, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + vq->vq_ring_size, /* max request size */ + 1, /* max # segments */ + vq->vq_ring_size, /* maxsegsize */ + BUS_DMA_COHERENT, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &vq->vq_ring_mtx, /* lockarg */ + &vq->vq_ring_dmat); + if (error) { + device_printf(dev, "cannot create bus_dma_tag\n"); + goto fail; + } + +#ifdef __powerpc__ + /* + * Virtio uses physical addresses rather than bus addresses, so we + * need to ask busdma to skip the iommu physical->bus mapping. At + * present, this is only a thing on the powerpc architectures. + */ + bus_dma_tag_set_iommu(vq->vq_ring_dmat, NULL, NULL); +#endif + if (info->vqai_maxindirsz > 1) { error = virtqueue_init_indirect(vq, info->vqai_maxindirsz); if (error) goto fail; } - vq->vq_ring_size = round_page(vring_size(size, align)); - vq->vq_ring_mem = contigmalloc(vq->vq_ring_size, M_DEVBUF, - M_NOWAIT | M_ZERO, 0, highaddr, PAGE_SIZE, 0); - if (vq->vq_ring_mem == NULL) { - device_printf(dev, - "cannot allocate memory for virtqueue ring\n"); - error = ENOMEM; + error = bus_dmamem_alloc(vq->vq_ring_dmat, &vq->vq_ring_mem, + BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, + &vq->vq_ring_mapp); + if (error) { + device_printf(dev, "bus_dmamem_alloc failed\n"); + goto fail; + } + + error = bus_dmamap_load(vq->vq_ring_dmat, vq->vq_ring_mapp, + vq->vq_ring_mem, vq->vq_ring_size, virtqueue_ring_load_callback, + vq, BUS_DMA_NOWAIT); + if (error) { + device_printf(dev, "vq->vq_ring_mapp load failed\n"); goto fail; } @@ -227,12 +291,29 @@ fail: return (error); } +static void +virtqueue_indirect_load_callback(void *arg, bus_dma_segment_t *segs, + int nsegs, int error) +{ + struct vq_desc_extra *dxp; + + if (error != 0) + return; + + KASSERT(nsegs == 1, ("%s: %d segments returned!", __func__, nsegs)); + + dxp = (struct vq_desc_extra *)arg; + dxp->indirect_paddr = segs[0].ds_addr; +} + static int virtqueue_init_indirect(struct virtqueue *vq, int indirect_size) { device_t dev; struct vq_desc_extra *dxp; int i, size; + int error; + int align; dev = vq->vq_dev; @@ -254,16 +335,61 @@ virtqueue_init_indirect(struct virtqueue *vq, int indirect_size) vq->vq_indirect_mem_size = size; vq->vq_flags |= VIRTQUEUE_FLAG_INDIRECT; + mtx_init(&vq->vq_indirect_mtx, device_get_nameunit(dev), + "VirtIO Indirect Queue Lock", MTX_DEF); + + align = size; + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + roundup_pow_of_two(align), /* alignment */ + 0, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + size, /* max request size */ + 1, /* max # segments */ + size, /* maxsegsize */ + BUS_DMA_COHERENT, /* flags */ + busdma_lock_mutex, /* lockfunc */ + &vq->vq_indirect_mtx, /* lockarg */ + &vq->vq_indirect_dmat); + if (error) { + device_printf(dev, "cannot create indirect bus_dma_tag\n"); + return (error); + } + +#ifdef __powerpc__ + /* + * Virtio uses physical addresses rather than bus addresses, so we + * need to ask busdma to skip the iommu physical->bus mapping. At + * present, this is only a thing on the powerpc architectures. + */ + bus_dma_tag_set_iommu(vq->vq_indirect_dmat, NULL, NULL); +#endif + for (i = 0; i < vq->vq_nentries; i++) { dxp = &vq->vq_descx[i]; - dxp->indirect = malloc(size, M_DEVBUF, M_NOWAIT); - if (dxp->indirect == NULL) { - device_printf(dev, "cannot allocate indirect list\n"); - return (ENOMEM); + error = bus_dmamem_alloc(vq->vq_indirect_dmat, + (void **)&dxp->indirect, + BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_COHERENT, + &dxp->mapp); + if (error) { + panic("dxp->mapp alloc failed\n"); + return (error); + } + + error = bus_dmamap_load(vq->vq_indirect_dmat, dxp->mapp, + dxp->indirect, size, virtqueue_indirect_load_callback, dxp, + BUS_DMA_NOWAIT); + if (error) { + panic("dxp->mapp load failed\n"); + bus_dmamem_free(vq->vq_indirect_dmat, dxp->indirect, + dxp->mapp); + dxp->indirect = NULL; + return (error); } - dxp->indirect_paddr = vtophys(dxp->indirect); virtqueue_init_indirect_list(vq, dxp->indirect); } @@ -282,7 +408,8 @@ virtqueue_free_indirect(struct virtqueue *vq) if (dxp->indirect == NULL) break; - free(dxp->indirect, M_DEVBUF); + bus_dmamap_unload(vq->vq_indirect_dmat, dxp->mapp); + bus_dmamem_free(vq->vq_indirect_dmat, dxp->indirect, dxp->mapp); dxp->indirect = NULL; dxp->indirect_paddr = 0; } @@ -360,9 +487,14 @@ virtqueue_free(struct virtqueue *vq) virtqueue_free_indirect(vq); if (vq->vq_ring_mem != NULL) { - free(vq->vq_ring_mem, M_DEVBUF); + bus_dmamap_unload(vq->vq_ring_dmat, vq->vq_ring_mapp); + bus_dmamem_free(vq->vq_ring_dmat, vq->vq_ring_mem, + vq->vq_ring_mapp); vq->vq_ring_size = 0; - vq->vq_ring_mem = NULL; + } + + if (vq->vq_ring_dmat != NULL) { + bus_dma_tag_destroy(vq->vq_ring_dmat); } free(vq, M_DEVBUF); @@ -371,29 +503,25 @@ virtqueue_free(struct virtqueue *vq) vm_paddr_t virtqueue_paddr(struct virtqueue *vq) { - - return (vtophys(vq->vq_ring_mem)); + return (vq->vq_ring_paddr); } vm_paddr_t virtqueue_desc_paddr(struct virtqueue *vq) { - - return (vtophys(vq->vq_ring.desc)); + return (vq->vq_ring.desc_paddr); } vm_paddr_t virtqueue_avail_paddr(struct virtqueue *vq) { - - return (vtophys(vq->vq_ring.avail)); + return (vq->vq_ring.avail_paddr); } vm_paddr_t virtqueue_used_paddr(struct virtqueue *vq) { - - return (vtophys(vq->vq_ring.used)); + return (vq->vq_ring.used_paddr); } uint16_t @@ -434,9 +562,12 @@ virtqueue_full(struct virtqueue *vq) void virtqueue_notify(struct virtqueue *vq) { - /* Ensure updated avail->idx is visible to host. */ + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_PREWRITE); +#if defined(__i386__) || defined(__amd64__) mb(); +#endif if (vq_ring_must_notify_host(vq)) vq_ring_notify_host(vq); @@ -448,6 +579,9 @@ virtqueue_nused(struct virtqueue *vq) { uint16_t used_idx, nused; + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_POSTREAD); + used_idx = vq_htog16(vq, vq->vq_ring.used->idx); nused = (uint16_t)(used_idx - vq->vq_used_cons_idx); @@ -459,6 +593,8 @@ virtqueue_nused(struct virtqueue *vq) int virtqueue_intr_filter(struct virtqueue *vq) { + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_POSTREAD); if (vq->vq_used_cons_idx == vq_htog16(vq, vq->vq_ring.used->idx)) return (0); @@ -487,6 +623,9 @@ virtqueue_postpone_intr(struct virtqueue *vq, vq_postpone_t hint) { uint16_t ndesc, avail_idx; + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_POSTREAD); + avail_idx = vq_htog16(vq, vq->vq_ring.avail->idx); ndesc = (uint16_t)(avail_idx - vq->vq_used_cons_idx); @@ -518,6 +657,9 @@ virtqueue_disable_intr(struct virtqueue *vq) } vq->vq_ring.avail->flags |= vq_gtoh16(vq, VRING_AVAIL_F_NO_INTERRUPT); + + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_PREWRITE); } int @@ -561,6 +703,9 @@ virtqueue_enqueue(struct virtqueue *vq, void *cookie, struct sglist *sg, idx = vq_ring_enqueue_segments(vq, vq->vq_ring.desc, head_idx, sg, readable, writable); + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_PREWRITE); + vq->vq_desc_head_idx = idx; vq->vq_free_cnt -= needed; if (vq->vq_free_cnt == 0) @@ -580,6 +725,9 @@ virtqueue_dequeue(struct virtqueue *vq, uint32_t *len) void *cookie; uint16_t used_idx, desc_idx; + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_POSTREAD); + if (vq->vq_used_cons_idx == vq_htog16(vq, atomic_load_16(&vq->vq_ring.used->idx))) return (NULL); @@ -666,11 +814,14 @@ vq_ring_init(struct virtqueue *vq) size = vq->vq_nentries; vr = &vq->vq_ring; - vring_init(vr, size, ring_mem, vq->vq_alignment); + vring_init(vr, size, ring_mem, vq->vq_ring_paddr, vq->vq_alignment); for (i = 0; i < size - 1; i++) vr->desc[i].next = vq_gtoh16(vq, i + 1); vr->desc[i].next = vq_gtoh16(vq, VQ_RING_DESC_CHAIN_END); + + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_PREWRITE); } static void @@ -694,6 +845,9 @@ vq_ring_update_avail(struct virtqueue *vq, uint16_t desc_idx) /* Keep pending count until virtqueue_notify(). */ vq->vq_queued_cnt++; + + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_PREWRITE); } static uint16_t @@ -777,6 +931,10 @@ vq_ring_enqueue_indirect(struct virtqueue *vq, void *cookie, vq_ring_enqueue_segments(vq, dxp->indirect, 0, sg, readable, writable); + bus_dmamap_sync(vq->vq_indirect_dmat, dxp->mapp, BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_PREWRITE); + vq->vq_desc_head_idx = vq_htog16(vq, dp->next); vq->vq_free_cnt--; if (vq->vq_free_cnt == 0) @@ -803,7 +961,11 @@ vq_ring_enable_interrupt(struct virtqueue *vq, uint16_t ndesc) vq_gtoh16(vq, ~VRING_AVAIL_F_NO_INTERRUPT); } + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_PREWRITE); +#if defined(__i386__) || defined(__amd64__) mb(); +#endif /* * Enough items may have already been consumed to meet our threshold @@ -821,6 +983,9 @@ vq_ring_must_notify_host(struct virtqueue *vq) { uint16_t new_idx, prev_idx, event_idx, flags; + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_POSTREAD); + if (vq->vq_flags & VIRTQUEUE_FLAG_EVENT_IDX) { new_idx = vq_htog16(vq, vq->vq_ring.avail->idx); prev_idx = new_idx - vq->vq_queued_cnt; @@ -876,4 +1041,7 @@ vq_ring_free_chain(struct virtqueue *vq, uint16_t desc_idx) */ dp->next = vq_gtoh16(vq, vq->vq_desc_head_idx); vq->vq_desc_head_idx = desc_idx; + + bus_dmamap_sync(vq->vq_ring_dmat, vq->vq_ring_mapp, + BUS_DMASYNC_PREWRITE); } diff --git a/sys/dev/vmgenc/vmgenc_acpi.c b/sys/dev/vmgenc/vmgenc_acpi.c index 18519a8e4f22..59fcbd5346ba 100644 --- a/sys/dev/vmgenc/vmgenc_acpi.c +++ b/sys/dev/vmgenc/vmgenc_acpi.c @@ -261,4 +261,4 @@ static driver_t vmgenc_driver = { DRIVER_MODULE(vmgenc, acpi, vmgenc_driver, NULL, NULL); MODULE_DEPEND(vmgenc, acpi, 1, 1, 1); -MODULE_DEPEND(vemgenc, random_harvestq, 1, 1, 1); +MODULE_DEPEND(vmgenc, random_harvestq, 1, 1, 1); diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c index 840e810a39fb..a2775023838a 100644 --- a/sys/dev/vmm/vmm_dev.c +++ b/sys/dev/vmm/vmm_dev.c @@ -8,6 +8,8 @@ #include <sys/param.h> #include <sys/conf.h> +#define EXTERR_CATEGORY EXTERR_CAT_VMM +#include <sys/exterrvar.h> #include <sys/fcntl.h> #include <sys/ioccom.h> #include <sys/jail.h> @@ -33,6 +35,7 @@ #include <dev/vmm/vmm_dev.h> #include <dev/vmm/vmm_mem.h> #include <dev/vmm/vmm_stat.h> +#include <dev/vmm/vmm_vm.h> #ifdef __amd64__ #ifdef COMPAT_FREEBSD12 @@ -90,7 +93,7 @@ static bool vmm_initialized = false; static SLIST_HEAD(, vmmdev_softc) head; -static unsigned pr_allow_flag; +static unsigned int pr_allow_vmm_flag, pr_allow_vmm_ppt_flag; static struct sx vmmdev_mtx; SX_SYSINIT(vmmdev_mtx, &vmmdev_mtx, "vmm device mutex"); @@ -111,10 +114,10 @@ static int devmem_create_cdev(struct vmmdev_softc *sc, int id, char *devmem); static void vmmdev_destroy(struct vmmdev_softc *sc); static int -vmm_priv_check(struct ucred *ucred) +vmm_jail_priv_check(struct ucred *ucred) { if (jailed(ucred) && - !(ucred->cr_prison->pr_allow & pr_allow_flag)) + (ucred->cr_prison->pr_allow & pr_allow_vmm_flag) == 0) return (EPERM); return (0); @@ -140,38 +143,6 @@ vcpu_unlock_one(struct vcpu *vcpu) vcpu_set_state(vcpu, VCPU_IDLE, false); } -#ifndef __amd64__ -static int -vcpu_set_state_all(struct vm *vm, enum vcpu_state newstate) -{ - struct vcpu *vcpu; - int error; - uint16_t i, j, maxcpus; - - error = 0; - maxcpus = vm_get_maxcpus(vm); - for (i = 0; i < maxcpus; i++) { - vcpu = vm_vcpu(vm, i); - if (vcpu == NULL) - continue; - error = vcpu_lock_one(vcpu); - if (error) - break; - } - - if (error) { - for (j = 0; j < i; j++) { - vcpu = vm_vcpu(vm, j); - if (vcpu == NULL) - continue; - vcpu_unlock_one(vcpu); - } - } - - return (error); -} -#endif - static int vcpu_lock_all(struct vmmdev_softc *sc) { @@ -400,7 +371,7 @@ vmmdev_open(struct cdev *dev, int flags, int fmt, struct thread *td) * A jail without vmm access shouldn't be able to access vmm device * files at all, but check here just to be thorough. */ - error = vmm_priv_check(td->td_ucred); + error = vmm_jail_priv_check(td->td_ucred); if (error != 0) return (error); @@ -490,8 +461,11 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, if (ioctl == NULL) return (ENOTTY); - if ((ioctl->flags & VMMDEV_IOCTL_PRIV_CHECK_DRIVER) != 0) { - error = priv_check(td, PRIV_DRIVER); + if ((ioctl->flags & VMMDEV_IOCTL_PPT) != 0) { + if (jailed(td->td_ucred) && (td->td_ucred->cr_prison->pr_allow & + pr_allow_vmm_ppt_flag) == 0) + return (EPERM); + error = priv_check(td, PRIV_VMM_PPTDEV); if (error != 0) return (error); } @@ -907,8 +881,7 @@ vmmdev_destroy(struct vmmdev_softc *sc) free(dsc, M_VMMDEV); } - if (sc->vm != NULL) - vm_destroy(sc->vm); + vm_destroy(sc->vm); chgvmmcnt(sc->ucred->cr_ruidinfo, -1, 0); crfree(sc->ucred); @@ -927,6 +900,7 @@ vmmdev_lookup_and_destroy(const char *name, struct ucred *cred) { struct cdev *cdev; struct vmmdev_softc *sc; + int error; sx_xlock(&vmmdev_mtx); sc = vmmdev_lookup(name, cred); @@ -936,6 +910,16 @@ vmmdev_lookup_and_destroy(const char *name, struct ucred *cred) } /* + * Only the creator of a VM or a privileged user can destroy it. + */ + if ((cred->cr_uid != sc->ucred->cr_uid || + cred->cr_prison != sc->ucred->cr_prison) && + (error = priv_check_cred(cred, PRIV_VMM_DESTROY)) != 0) { + sx_xunlock(&vmmdev_mtx); + return (error); + } + + /* * Setting 'sc->cdev' to NULL is used to indicate that the VM * is scheduled for destruction. */ @@ -956,7 +940,7 @@ sysctl_vmm_destroy(SYSCTL_HANDLER_ARGS) char *buf; int error, buflen; - error = vmm_priv_check(req->td->td_ucred); + error = vmm_jail_priv_check(req->td->td_ucred); if (error) return (error); @@ -1021,9 +1005,32 @@ vmmdev_create(const char *name, uint32_t flags, struct ucred *cred) return (EEXIST); } + /* + * Unprivileged users can only create VMs that will be automatically + * destroyed when the creating descriptor is closed. + */ + if ((flags & VMMCTL_CREATE_DESTROY_ON_CLOSE) == 0 && + (error = priv_check_cred(cred, PRIV_VMM_CREATE)) != 0) { + sx_xunlock(&vmmdev_mtx); + return (EXTERROR(error, + "An unprivileged user must run VMs in monitor mode")); + } + + if ((error = vmm_jail_priv_check(cred)) != 0) { + sx_xunlock(&vmmdev_mtx); + return (EXTERROR(error, + "VMs cannot be created in the current jail")); + } + + if (!chgvmmcnt(cred->cr_ruidinfo, 1, vm_maxvmms)) { + sx_xunlock(&vmmdev_mtx); + return (ENOMEM); + } + error = vm_create(name, &vm); if (error != 0) { sx_xunlock(&vmmdev_mtx); + (void)chgvmmcnt(cred->cr_ruidinfo, -1, 0); return (error); } sc = vmmdev_alloc(vm, cred); @@ -1035,8 +1042,8 @@ vmmdev_create(const char *name, uint32_t flags, struct ucred *cred) make_dev_args_init(&mda); mda.mda_devsw = &vmmdevsw; mda.mda_cr = sc->ucred; - mda.mda_uid = UID_ROOT; - mda.mda_gid = GID_WHEEL; + mda.mda_uid = cred->cr_uid; + mda.mda_gid = GID_VMM; mda.mda_mode = 0600; mda.mda_si_drv1 = sc; mda.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK; @@ -1046,12 +1053,6 @@ vmmdev_create(const char *name, uint32_t flags, struct ucred *cred) vmmdev_destroy(sc); return (error); } - if (!chgvmmcnt(cred->cr_ruidinfo, 1, vm_maxvmms)) { - sx_xunlock(&vmmdev_mtx); - destroy_dev(cdev); - vmmdev_destroy(sc); - return (ENOMEM); - } sc->cdev = cdev; sx_xunlock(&vmmdev_mtx); return (0); @@ -1066,7 +1067,7 @@ sysctl_vmm_create(SYSCTL_HANDLER_ARGS) if (!vmm_initialized) return (ENXIO); - error = vmm_priv_check(req->td->td_ucred); + error = vmm_jail_priv_check(req->td->td_ucred); if (error != 0) return (error); @@ -1131,7 +1132,7 @@ vmmctl_open(struct cdev *cdev, int flags, int fmt, struct thread *td) int error; struct vmmctl_priv *priv; - error = vmm_priv_check(td->td_ucred); + error = vmm_jail_priv_check(td->td_ucred); if (error != 0) return (error); @@ -1209,10 +1210,13 @@ vmmdev_init(void) sx_xlock(&vmmdev_mtx); error = make_dev_p(MAKEDEV_CHECKNAME, &vmmctl_cdev, &vmmctlsw, NULL, - UID_ROOT, GID_WHEEL, 0600, "vmmctl"); - if (error == 0) - pr_allow_flag = prison_add_allow(NULL, "vmm", NULL, - "Allow use of vmm in a jail."); + UID_ROOT, GID_VMM, 0660, "vmmctl"); + if (error == 0) { + pr_allow_vmm_flag = prison_add_allow(NULL, "vmm", NULL, + "Allow use of vmm in a jail"); + pr_allow_vmm_ppt_flag = prison_add_allow(NULL, "vmm_ppt", NULL, + "Allow use of vmm with ppt devices in a jail"); + } sx_xunlock(&vmmdev_mtx); return (error); @@ -1259,9 +1263,11 @@ vmm_handler(module_t mod, int what, void *arg) if (error == 0) vmm_initialized = true; else { - error = vmmdev_cleanup(); - KASSERT(error == 0, - ("%s: vmmdev_cleanup failed: %d", __func__, error)); + int error1 __diagused; + + error1 = vmmdev_cleanup(); + KASSERT(error1 == 0, + ("%s: vmmdev_cleanup failed: %d", __func__, error1)); } break; case MOD_UNLOAD: @@ -1360,8 +1366,8 @@ devmem_create_cdev(struct vmmdev_softc *sc, int segid, char *devname) make_dev_args_init(&mda); mda.mda_devsw = &devmemsw; mda.mda_cr = sc->ucred; - mda.mda_uid = UID_ROOT; - mda.mda_gid = GID_WHEEL; + mda.mda_uid = sc->ucred->cr_uid; + mda.mda_gid = GID_VMM; mda.mda_mode = 0600; mda.mda_si_drv1 = dsc; mda.mda_flags = MAKEDEV_CHECKNAME | MAKEDEV_WAITOK; diff --git a/sys/dev/vmm/vmm_dev.h b/sys/dev/vmm/vmm_dev.h index f8f637fda687..4b971d88f80e 100644 --- a/sys/dev/vmm/vmm_dev.h +++ b/sys/dev/vmm/vmm_dev.h @@ -48,7 +48,7 @@ struct vmmdev_ioctl { #define VMMDEV_IOCTL_LOCK_ALL_VCPUS 0x08 #define VMMDEV_IOCTL_ALLOC_VCPU 0x10 #define VMMDEV_IOCTL_MAYBE_ALLOC_VCPU 0x20 -#define VMMDEV_IOCTL_PRIV_CHECK_DRIVER 0x40 +#define VMMDEV_IOCTL_PPT 0x40 int flags; }; diff --git a/sys/dev/vmm/vmm_ktr.h b/sys/dev/vmm/vmm_ktr.h index 20370a229530..afd9831e4225 100644 --- a/sys/dev/vmm/vmm_ktr.h +++ b/sys/dev/vmm/vmm_ktr.h @@ -30,7 +30,9 @@ #define _VMM_KTR_H_ #include <sys/ktr.h> -#include <sys/pcpu.h> +#ifdef KTR +#include <dev/vmm/vmm_vm.h> +#endif #ifndef KTR_VMM #define KTR_VMM KTR_GEN diff --git a/sys/dev/vmm/vmm_mem.c b/sys/dev/vmm/vmm_mem.c index 5ae944713c81..143020968de3 100644 --- a/sys/dev/vmm/vmm_mem.c +++ b/sys/dev/vmm/vmm_mem.c @@ -23,6 +23,7 @@ #include <dev/vmm/vmm_dev.h> #include <dev/vmm/vmm_mem.h> +#include <dev/vmm/vmm_vm.h> static void vm_free_memmap(struct vm *vm, int ident); @@ -448,7 +449,7 @@ _vm_gpa_hold(struct vm *vm, vm_paddr_t gpa, size_t len, int reqprot, if (count == 1) { *cookie = m; - return ((void *)(PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)) + pageoff)); + return ((char *)VM_PAGE_TO_DMAP(m) + pageoff); } else { *cookie = NULL; return (NULL); diff --git a/sys/dev/vmm/vmm_mem.h b/sys/dev/vmm/vmm_mem.h index f3d22058c7b8..64bb29352a55 100644 --- a/sys/dev/vmm/vmm_mem.h +++ b/sys/dev/vmm/vmm_mem.h @@ -34,7 +34,10 @@ enum { #include <sys/types.h> #include <sys/_sx.h> +struct domainset; +struct vcpu; struct vm; +struct vm_guest_paging; struct vm_object; struct vmspace; diff --git a/sys/dev/vmm/vmm_stat.h b/sys/dev/vmm/vmm_stat.h index 471afd0dd827..469d8ef54829 100644 --- a/sys/dev/vmm/vmm_stat.h +++ b/sys/dev/vmm/vmm_stat.h @@ -32,6 +32,8 @@ #ifndef _DEV_VMM_STAT_H_ #define _DEV_VMM_STAT_H_ +#include <dev/vmm/vmm_vm.h> + struct vm; #define MAX_VMM_STAT_ELEMS 64 /* arbitrary */ diff --git a/sys/dev/vmm/vmm_vm.c b/sys/dev/vmm/vmm_vm.c new file mode 100644 index 000000000000..7941038ed671 --- /dev/null +++ b/sys/dev/vmm/vmm_vm.c @@ -0,0 +1,476 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2011 NetApp, Inc. + * All rights reserved. + */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/lock.h> +#include <sys/mutex.h> +#include <sys/proc.h> +#include <sys/sx.h> +#include <sys/sysctl.h> + +#include <machine/smp.h> + +#include <dev/vmm/vmm_vm.h> + +SYSCTL_NODE(_hw, OID_AUTO, vmm, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, NULL); + +int vmm_ipinum; +SYSCTL_INT(_hw_vmm, OID_AUTO, ipinum, CTLFLAG_RD, &vmm_ipinum, 0, + "IPI vector used for vcpu notifications"); + +/* + * Invoke the rendezvous function on the specified vcpu if applicable. Return + * true if the rendezvous is finished, false otherwise. + */ +static bool +vm_rendezvous(struct vcpu *vcpu) +{ + struct vm *vm = vcpu->vm; + int vcpuid; + + mtx_assert(&vcpu->vm->rendezvous_mtx, MA_OWNED); + KASSERT(vcpu->vm->rendezvous_func != NULL, + ("vm_rendezvous: no rendezvous pending")); + + /* 'rendezvous_req_cpus' must be a subset of 'active_cpus' */ + CPU_AND(&vm->rendezvous_req_cpus, &vm->rendezvous_req_cpus, + &vm->active_cpus); + + vcpuid = vcpu->vcpuid; + if (CPU_ISSET(vcpuid, &vm->rendezvous_req_cpus) && + !CPU_ISSET(vcpuid, &vm->rendezvous_done_cpus)) { + (*vm->rendezvous_func)(vcpu, vm->rendezvous_arg); + CPU_SET(vcpuid, &vm->rendezvous_done_cpus); + } + if (CPU_CMP(&vm->rendezvous_req_cpus, &vm->rendezvous_done_cpus) == 0) { + CPU_ZERO(&vm->rendezvous_req_cpus); + vm->rendezvous_func = NULL; + wakeup(&vm->rendezvous_func); + return (true); + } + return (false); +} + +int +vm_handle_rendezvous(struct vcpu *vcpu) +{ + struct vm *vm; + struct thread *td; + + td = curthread; + vm = vcpu->vm; + + mtx_lock(&vm->rendezvous_mtx); + while (vm->rendezvous_func != NULL) { + if (vm_rendezvous(vcpu)) + break; + + mtx_sleep(&vm->rendezvous_func, &vm->rendezvous_mtx, 0, + "vmrndv", hz); + if (td_ast_pending(td, TDA_SUSPEND)) { + int error; + + mtx_unlock(&vm->rendezvous_mtx); + error = thread_check_susp(td, true); + if (error != 0) + return (error); + mtx_lock(&vm->rendezvous_mtx); + } + } + mtx_unlock(&vm->rendezvous_mtx); + return (0); +} + +static void +vcpu_wait_idle(struct vcpu *vcpu) +{ + KASSERT(vcpu->state != VCPU_IDLE, ("vcpu already idle")); + + vcpu->reqidle = 1; + vcpu_notify_event_locked(vcpu); + msleep_spin(&vcpu->state, &vcpu->mtx, "vmstat", hz); +} + +int +vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate, + bool from_idle) +{ + int error; + + vcpu_assert_locked(vcpu); + + /* + * State transitions from the vmmdev_ioctl() must always begin from + * the VCPU_IDLE state. This guarantees that there is only a single + * ioctl() operating on a vcpu at any point. + */ + if (from_idle) { + while (vcpu->state != VCPU_IDLE) + vcpu_wait_idle(vcpu); + } else { + KASSERT(vcpu->state != VCPU_IDLE, ("invalid transition from " + "vcpu idle state")); + } + + if (vcpu->state == VCPU_RUNNING) { + KASSERT(vcpu->hostcpu == curcpu, ("curcpu %d and hostcpu %d " + "mismatch for running vcpu", curcpu, vcpu->hostcpu)); + } else { + KASSERT(vcpu->hostcpu == NOCPU, ("Invalid hostcpu %d for a " + "vcpu that is not running", vcpu->hostcpu)); + } + + /* + * The following state transitions are allowed: + * IDLE -> FROZEN -> IDLE + * FROZEN -> RUNNING -> FROZEN + * FROZEN -> SLEEPING -> FROZEN + */ + switch (vcpu->state) { + case VCPU_IDLE: + case VCPU_RUNNING: + case VCPU_SLEEPING: + error = (newstate != VCPU_FROZEN); + break; + case VCPU_FROZEN: + error = (newstate == VCPU_FROZEN); + break; + default: + error = 1; + break; + } + + if (error) + return (EBUSY); + + vcpu->state = newstate; + if (newstate == VCPU_RUNNING) + vcpu->hostcpu = curcpu; + else + vcpu->hostcpu = NOCPU; + + if (newstate == VCPU_IDLE) + wakeup(&vcpu->state); + + return (0); +} + +/* + * Try to lock all of the vCPUs in the VM while taking care to avoid deadlocks + * with vm_smp_rendezvous(). + * + * The complexity here suggests that the rendezvous mechanism needs a rethink. + */ +int +vcpu_set_state_all(struct vm *vm, enum vcpu_state newstate) +{ + cpuset_t locked; + struct vcpu *vcpu; + int error, i; + uint16_t maxcpus; + + KASSERT(newstate != VCPU_IDLE, + ("vcpu_set_state_all: invalid target state %d", newstate)); + + error = 0; + CPU_ZERO(&locked); + maxcpus = vm->maxcpus; + + mtx_lock(&vm->rendezvous_mtx); +restart: + if (vm->rendezvous_func != NULL) { + /* + * If we have a pending rendezvous, then the initiator may be + * blocked waiting for other vCPUs to execute the callback. The + * current thread may be a vCPU thread so we must not block + * waiting for the initiator, otherwise we get a deadlock. + * Thus, execute the callback on behalf of any idle vCPUs. + */ + for (i = 0; i < maxcpus; i++) { + vcpu = vm_vcpu(vm, i); + if (vcpu == NULL) + continue; + vcpu_lock(vcpu); + if (vcpu->state == VCPU_IDLE) { + (void)vcpu_set_state_locked(vcpu, VCPU_FROZEN, + true); + CPU_SET(i, &locked); + } + if (CPU_ISSET(i, &locked)) { + /* + * We can safely execute the callback on this + * vCPU's behalf. + */ + vcpu_unlock(vcpu); + (void)vm_rendezvous(vcpu); + vcpu_lock(vcpu); + } + vcpu_unlock(vcpu); + } + } + + /* + * Now wait for remaining vCPUs to become idle. This may include the + * initiator of a rendezvous that is currently blocked on the rendezvous + * mutex. + */ + CPU_FOREACH_ISCLR(i, &locked) { + if (i >= maxcpus) + break; + vcpu = vm_vcpu(vm, i); + if (vcpu == NULL) + continue; + vcpu_lock(vcpu); + while (vcpu->state != VCPU_IDLE) { + mtx_unlock(&vm->rendezvous_mtx); + vcpu_wait_idle(vcpu); + vcpu_unlock(vcpu); + mtx_lock(&vm->rendezvous_mtx); + if (vm->rendezvous_func != NULL) + goto restart; + vcpu_lock(vcpu); + } + error = vcpu_set_state_locked(vcpu, newstate, true); + vcpu_unlock(vcpu); + if (error != 0) { + /* Roll back state changes. */ + CPU_FOREACH_ISSET(i, &locked) + (void)vcpu_set_state(vcpu, VCPU_IDLE, false); + break; + } + CPU_SET(i, &locked); + } + mtx_unlock(&vm->rendezvous_mtx); + return (error); +} + + +int +vcpu_set_state(struct vcpu *vcpu, enum vcpu_state newstate, bool from_idle) +{ + int error; + + vcpu_lock(vcpu); + error = vcpu_set_state_locked(vcpu, newstate, from_idle); + vcpu_unlock(vcpu); + + return (error); +} + +enum vcpu_state +vcpu_get_state(struct vcpu *vcpu, int *hostcpu) +{ + enum vcpu_state state; + + vcpu_lock(vcpu); + state = vcpu->state; + if (hostcpu != NULL) + *hostcpu = vcpu->hostcpu; + vcpu_unlock(vcpu); + + return (state); +} + +/* + * This function is called to ensure that a vcpu "sees" a pending event + * as soon as possible: + * - If the vcpu thread is sleeping then it is woken up. + * - If the vcpu is running on a different host_cpu then an IPI will be directed + * to the host_cpu to cause the vcpu to trap into the hypervisor. + */ +void +vcpu_notify_event_locked(struct vcpu *vcpu) +{ + int hostcpu; + + hostcpu = vcpu->hostcpu; + if (vcpu->state == VCPU_RUNNING) { + KASSERT(hostcpu != NOCPU, ("vcpu running on invalid hostcpu")); + if (hostcpu != curcpu) { + ipi_cpu(hostcpu, vmm_ipinum); + } else { + /* + * If the 'vcpu' is running on 'curcpu' then it must + * be sending a notification to itself (e.g. SELF_IPI). + * The pending event will be picked up when the vcpu + * transitions back to guest context. + */ + } + } else { + KASSERT(hostcpu == NOCPU, ("vcpu state %d not consistent " + "with hostcpu %d", vcpu->state, hostcpu)); + if (vcpu->state == VCPU_SLEEPING) + wakeup_one(vcpu); + } +} + +void +vcpu_notify_event(struct vcpu *vcpu) +{ + vcpu_lock(vcpu); + vcpu_notify_event_locked(vcpu); + vcpu_unlock(vcpu); +} + +int +vcpu_debugged(struct vcpu *vcpu) +{ + return (CPU_ISSET(vcpu->vcpuid, &vcpu->vm->debug_cpus)); +} + +void +vm_lock_vcpus(struct vm *vm) +{ + sx_xlock(&vm->vcpus_init_lock); +} + +void +vm_unlock_vcpus(struct vm *vm) +{ + sx_unlock(&vm->vcpus_init_lock); +} + +void +vm_disable_vcpu_creation(struct vm *vm) +{ + sx_xlock(&vm->vcpus_init_lock); + vm->dying = true; + sx_xunlock(&vm->vcpus_init_lock); +} + +uint16_t +vm_get_maxcpus(struct vm *vm) +{ + return (vm->maxcpus); +} + +void +vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores, + uint16_t *threads, uint16_t *maxcpus) +{ + *sockets = vm->sockets; + *cores = vm->cores; + *threads = vm->threads; + *maxcpus = vm->maxcpus; +} + +int +vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores, + uint16_t threads, uint16_t maxcpus __unused) +{ + /* Ignore maxcpus. */ + if (sockets * cores * threads > vm->maxcpus) + return (EINVAL); + vm->sockets = sockets; + vm->cores = cores; + vm->threads = threads; + return (0); +} + +int +vm_suspend(struct vm *vm, enum vm_suspend_how how) +{ + int i; + + if (how <= VM_SUSPEND_NONE || how >= VM_SUSPEND_LAST) + return (EINVAL); + + if (atomic_cmpset_int(&vm->suspend, 0, how) == 0) + return (EALREADY); + + /* + * Notify all active vcpus that they are now suspended. + */ + for (i = 0; i < vm->maxcpus; i++) { + if (CPU_ISSET(i, &vm->active_cpus)) + vcpu_notify_event(vm_vcpu(vm, i)); + } + + return (0); +} + +int +vm_reinit(struct vm *vm) +{ + int error; + + /* + * A virtual machine can be reset only if all vcpus are suspended. + */ + if (CPU_CMP(&vm->suspended_cpus, &vm->active_cpus) == 0) { + vm_reset(vm); + error = 0; + } else { + error = EBUSY; + } + + return (error); +} + +int +vm_activate_cpu(struct vcpu *vcpu) +{ + struct vm *vm = vcpu->vm; + + if (CPU_ISSET(vcpu->vcpuid, &vm->active_cpus)) + return (EBUSY); + + CPU_SET_ATOMIC(vcpu->vcpuid, &vm->active_cpus); + return (0); +} + +int +vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu) +{ + if (vcpu == NULL) { + vm->debug_cpus = vm->active_cpus; + for (int i = 0; i < vm->maxcpus; i++) { + if (CPU_ISSET(i, &vm->active_cpus)) + vcpu_notify_event(vm_vcpu(vm, i)); + } + } else { + if (!CPU_ISSET(vcpu->vcpuid, &vm->active_cpus)) + return (EINVAL); + + CPU_SET_ATOMIC(vcpu->vcpuid, &vm->debug_cpus); + vcpu_notify_event(vcpu); + } + return (0); +} + +int +vm_resume_cpu(struct vm *vm, struct vcpu *vcpu) +{ + if (vcpu == NULL) { + CPU_ZERO(&vm->debug_cpus); + } else { + if (!CPU_ISSET(vcpu->vcpuid, &vm->debug_cpus)) + return (EINVAL); + + CPU_CLR_ATOMIC(vcpu->vcpuid, &vm->debug_cpus); + } + return (0); +} + +cpuset_t +vm_active_cpus(struct vm *vm) +{ + return (vm->active_cpus); +} + +cpuset_t +vm_debug_cpus(struct vm *vm) +{ + return (vm->debug_cpus); +} + +cpuset_t +vm_suspended_cpus(struct vm *vm) +{ + return (vm->suspended_cpus); +} diff --git a/sys/dev/vmm/vmm_vm.h b/sys/dev/vmm/vmm_vm.h new file mode 100644 index 000000000000..66d3545d1dd5 --- /dev/null +++ b/sys/dev/vmm/vmm_vm.h @@ -0,0 +1,233 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2011 NetApp, Inc. + * All rights reserved. + */ + +#ifndef _DEV_VMM_VM_H_ +#define _DEV_VMM_VM_H_ + +#ifdef _KERNEL +#include <sys/_cpuset.h> + +#include <machine/vmm.h> + +#include <dev/vmm/vmm_param.h> +#include <dev/vmm/vmm_mem.h> + +struct vcpu; + +enum vcpu_state { + VCPU_IDLE, + VCPU_FROZEN, + VCPU_RUNNING, + VCPU_SLEEPING, +}; + +/* + * Initialization: + * (a) allocated when vcpu is created + * (i) initialized when vcpu is created and when it is reinitialized + * (o) initialized the first time the vcpu is created + * (x) initialized before use + */ +struct vcpu { + struct mtx mtx; /* (o) protects 'state' and 'hostcpu' */ + enum vcpu_state state; /* (o) vcpu state */ + int vcpuid; /* (o) */ + int hostcpu; /* (o) vcpu's host cpu */ + int reqidle; /* (i) request vcpu to idle */ + struct vm *vm; /* (o) */ + void *cookie; /* (i) cpu-specific data */ + void *stats; /* (a,i) statistics */ + + VMM_VCPU_MD_FIELDS; +}; + +#define vcpu_lock_init(v) mtx_init(&((v)->mtx), "vcpu lock", 0, MTX_SPIN) +#define vcpu_lock_destroy(v) mtx_destroy(&((v)->mtx)) +#define vcpu_lock(v) mtx_lock_spin(&((v)->mtx)) +#define vcpu_unlock(v) mtx_unlock_spin(&((v)->mtx)) +#define vcpu_assert_locked(v) mtx_assert(&((v)->mtx), MA_OWNED) + +extern int vmm_ipinum; + +int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle); +int vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate, + bool from_idle); +int vcpu_set_state_all(struct vm *vm, enum vcpu_state state); +enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu); +void vcpu_notify_event(struct vcpu *vcpu); +void vcpu_notify_event_locked(struct vcpu *vcpu); +int vcpu_debugged(struct vcpu *vcpu); + +static inline void * +vcpu_stats(struct vcpu *vcpu) +{ + return (vcpu->stats); +} + +static inline struct vm * +vcpu_vm(struct vcpu *vcpu) +{ + return (vcpu->vm); +} + +static inline int +vcpu_vcpuid(struct vcpu *vcpu) +{ + return (vcpu->vcpuid); +} + +static int __inline +vcpu_is_running(struct vcpu *vcpu, int *hostcpu) +{ + return (vcpu_get_state(vcpu, hostcpu) == VCPU_RUNNING); +} + +#ifdef _SYS_PROC_H_ +static int __inline +vcpu_should_yield(struct vcpu *vcpu) +{ + struct thread *td; + + td = curthread; + return (td->td_ast != 0 || td->td_owepreempt != 0); +} +#endif + +typedef void (*vm_rendezvous_func_t)(struct vcpu *vcpu, void *arg); +int vm_handle_rendezvous(struct vcpu *vcpu); + +/* + * Rendezvous all vcpus specified in 'dest' and execute 'func(arg)'. + * The rendezvous 'func(arg)' is not allowed to do anything that will + * cause the thread to be put to sleep. + * + * The caller cannot hold any locks when initiating the rendezvous. + * + * The implementation of this API may cause vcpus other than those specified + * by 'dest' to be stalled. The caller should not rely on any vcpus making + * forward progress when the rendezvous is in progress. + */ +int vm_smp_rendezvous(struct vcpu *vcpu, cpuset_t dest, + vm_rendezvous_func_t func, void *arg); + +/* + * Initialization: + * (o) initialized the first time the VM is created + * (i) initialized when VM is created and when it is reinitialized + * (x) initialized before use + * + * Locking: + * [m] mem_segs_lock + * [r] rendezvous_mtx + * [v] reads require one frozen vcpu, writes require freezing all vcpus + */ +struct vm { + void *cookie; /* (i) cpu-specific data */ + struct vcpu **vcpu; /* (o) guest vcpus */ + struct vm_mem mem; /* (i) [m+v] guest memory */ + + char name[VM_MAX_NAMELEN + 1]; /* (o) virtual machine name */ + struct sx vcpus_init_lock; /* (o) */ + + bool dying; /* (o) is dying */ + int suspend; /* (i) stop VM execution */ + + volatile cpuset_t active_cpus; /* (i) active vcpus */ + volatile cpuset_t debug_cpus; /* (i) vcpus stopped for debug */ + volatile cpuset_t suspended_cpus; /* (i) suspended vcpus */ + volatile cpuset_t halted_cpus; /* (x) cpus in a hard halt */ + + cpuset_t rendezvous_req_cpus; /* (x) [r] rendezvous requested */ + cpuset_t rendezvous_done_cpus; /* (x) [r] rendezvous finished */ + void *rendezvous_arg; /* (x) [r] rendezvous func/arg */ + vm_rendezvous_func_t rendezvous_func; + struct mtx rendezvous_mtx; /* (o) rendezvous lock */ + + uint16_t sockets; /* (o) num of sockets */ + uint16_t cores; /* (o) num of cores/socket */ + uint16_t threads; /* (o) num of threads/core */ + uint16_t maxcpus; /* (o) max pluggable cpus */ + + VMM_VM_MD_FIELDS; +}; + +int vm_create(const char *name, struct vm **retvm); +struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid); +void vm_destroy(struct vm *vm); +int vm_reinit(struct vm *vm); +void vm_reset(struct vm *vm); + +void vm_lock_vcpus(struct vm *vm); +void vm_unlock_vcpus(struct vm *vm); +void vm_disable_vcpu_creation(struct vm *vm); + +int vm_suspend(struct vm *vm, enum vm_suspend_how how); +int vm_activate_cpu(struct vcpu *vcpu); +int vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu); +int vm_resume_cpu(struct vm *vm, struct vcpu *vcpu); + +cpuset_t vm_active_cpus(struct vm *vm); +cpuset_t vm_debug_cpus(struct vm *vm); +cpuset_t vm_suspended_cpus(struct vm *vm); + +uint16_t vm_get_maxcpus(struct vm *vm); +void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores, + uint16_t *threads, uint16_t *maxcpus); +int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores, + uint16_t threads, uint16_t maxcpus); + +static inline const char * +vm_name(struct vm *vm) +{ + return (vm->name); +} + +static inline struct vm_mem * +vm_mem(struct vm *vm) +{ + return (&vm->mem); +} + +static inline struct vcpu * +vm_vcpu(struct vm *vm, int vcpuid) +{ + return (vm->vcpu[vcpuid]); +} + +struct vm_eventinfo { + cpuset_t *rptr; /* rendezvous cookie */ + int *sptr; /* suspend cookie */ + int *iptr; /* reqidle cookie */ +}; + +static inline int +vcpu_rendezvous_pending(struct vcpu *vcpu, struct vm_eventinfo *info) +{ + /* + * This check isn't done with atomic operations or under a lock because + * there's no need to. If the vcpuid bit is set, the vcpu is part of a + * rendezvous and the bit won't be cleared until the vcpu enters the + * rendezvous. On rendezvous exit, the cpuset is cleared and the vcpu + * will see an empty cpuset. So, the races are harmless. + */ + return (CPU_ISSET(vcpu_vcpuid(vcpu), info->rptr)); +} + +static inline int +vcpu_suspended(struct vm_eventinfo *info) +{ + return (*info->sptr); +} + +static inline int +vcpu_reqidle(struct vm_eventinfo *info) +{ + return (*info->iptr); +} +#endif /* _KERNEL */ + +#endif /* !_DEV_VMM_VM_H_ */ diff --git a/sys/dev/vnic/nicvf_queues.c b/sys/dev/vnic/nicvf_queues.c index 45d6b54b18ed..95185d39a3a8 100644 --- a/sys/dev/vnic/nicvf_queues.c +++ b/sys/dev/vnic/nicvf_queues.c @@ -116,7 +116,8 @@ struct rbuf_info { struct mbuf * mbuf; }; -#define GET_RBUF_INFO(x) ((struct rbuf_info *)((x) - NICVF_RCV_BUF_ALIGN_BYTES)) +#define GET_RBUF_INFO(x) \ + ((struct rbuf_info *)((char *)(x) - NICVF_RCV_BUF_ALIGN_BYTES)) /* Poll a register for a specific value */ static int nicvf_poll_reg(struct nicvf *nic, int qidx, diff --git a/sys/dev/vt/vt.h b/sys/dev/vt/vt.h index 8e35a81bc101..4abe99e4ab13 100644 --- a/sys/dev/vt/vt.h +++ b/sys/dev/vt/vt.h @@ -81,7 +81,6 @@ #else #define DPRINTF(_l, ...) do {} while (0) #endif -#define ISSIGVALID(sig) ((sig) > 0 && (sig) < NSIG) #define VT_SYSCTL_INT(_name, _default, _descr) \ int vt_##_name = (_default); \ diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index 5e8f7b1d0bb7..68a9a71c3d72 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -804,11 +804,11 @@ vt_machine_kbdevent(struct vt_device *vd, int c) return (1); case SPCLKEY | STBY: /* XXX Not present in kbdcontrol parser. */ /* Put machine into Stand-By mode. */ - power_pm_suspend(POWER_SLEEP_STATE_STANDBY); + power_pm_suspend(POWER_SSTATE_TRANSITION_STANDBY); return (1); case SPCLKEY | SUSP: /* kbdmap(5) keyword `susp`. */ /* Suspend machine. */ - power_pm_suspend(POWER_SLEEP_STATE_SUSPEND); + power_pm_suspend(POWER_SSTATE_TRANSITION_SUSPEND); return (1); } @@ -952,6 +952,9 @@ vt_processkey(keyboard_t *kbd, struct vt_device *vd, int c) VT_UNLOCK(vd); break; } + case BKEY | BTAB: /* Back tab (usually, shift+tab). */ + terminal_input_special(vw->vw_terminal, TKEY_BTAB); + break; case FKEY | F(1): case FKEY | F(2): case FKEY | F(3): case FKEY | F(4): case FKEY | F(5): case FKEY | F(6): case FKEY | F(7): case FKEY | F(8): case FKEY | F(9): @@ -1681,27 +1684,41 @@ vtterm_splash(struct vt_device *vd) uintptr_t image; vt_axis_t top, left; - si = MD_FETCH(preload_kmdp, MODINFOMD_SPLASH, struct splash_info *); - if (!(vd->vd_flags & VDF_TEXTMODE) && (boothowto & RB_MUTE)) { - if (si == NULL) { - top = (vd->vd_height - vt_logo_height) / 2; - left = (vd->vd_width - vt_logo_width) / 2; - vd->vd_driver->vd_bitblt_bmp(vd, vd->vd_curwindow, - vt_logo_image, NULL, vt_logo_width, vt_logo_height, - left, top, TC_WHITE, TC_BLACK); - } else { - if (si->si_depth != 4) - return; - image = (uintptr_t)si + sizeof(struct splash_info); - image = roundup2(image, 8); - top = (vd->vd_height - si->si_height) / 2; - left = (vd->vd_width - si->si_width) / 2; - vd->vd_driver->vd_bitblt_argb(vd, vd->vd_curwindow, - (unsigned char *)image, si->si_width, si->si_height, - left, top); - } - vd->vd_flags |= VDF_SPLASH; + if ((vd->vd_flags & VDF_TEXTMODE) != 0 || (boothowto & RB_MUTE) == 0) + return; + + si = MD_FETCH(preload_kmdp, rebooting == 1 ? MODINFOMD_SHTDWNSPLASH : + MODINFOMD_SPLASH, struct splash_info *); + if (si == NULL) { + if (vd->vd_driver->vd_bitblt_bmp == NULL) + return; + } else if (vd->vd_driver->vd_bitblt_argb == NULL) + return; + + if (rebooting == 1) { + if (vd->vd_driver->vd_blank == NULL) + return; + vd->vd_driver->vd_blank(vd, TC_BLACK); + } + + if (si == NULL) { + top = (vd->vd_height - vt_logo_height) / 2; + left = (vd->vd_width - vt_logo_width) / 2; + vd->vd_driver->vd_bitblt_bmp(vd, + vd->vd_curwindow, vt_logo_image, NULL, vt_logo_width, + vt_logo_height, left, top, TC_WHITE, TC_BLACK); + } else { + if (si->si_depth != 4) + return; + image = (uintptr_t)si + sizeof(struct splash_info); + image = roundup2(image, 8); + top = (vd->vd_height - si->si_height) / 2; + left = (vd->vd_width - si->si_width) / 2; + vd->vd_driver->vd_bitblt_argb(vd, vd->vd_curwindow, + (unsigned char *)image, si->si_width, si->si_height, + left, top); } + vd->vd_flags |= VDF_SPLASH; } #endif @@ -1829,6 +1846,15 @@ vt_init_font_static(void) vt_font_assigned = font; } +#ifdef DEV_SPLASH +static int +vt_shutdown_splash(struct vt_window *vw) +{ + vtterm_splash(vw->vw_device); + return (0); +} +#endif + static void vtterm_cnprobe(struct terminal *tm, struct consdev *cp) { @@ -1964,6 +1990,9 @@ vtterm_cngetc(struct terminal *tm) VTBUF_SLCK_DISABLE(&vw->vw_buf); } break; + case SPCLKEY | BTAB: /* Back tab (usually, shift+tab). */ + vw->vw_kbdsq = "\x1b[Z"; + break; /* XXX: KDB can handle history. */ case SPCLKEY | FKEY | F(50): /* Arrow up. */ vw->vw_kbdsq = "\x1b[A"; @@ -3046,9 +3075,9 @@ skip_thunk: DPRINTF(5, "reset WAIT_ACQ, "); return (0); } else if (mode->mode == VT_PROCESS) { - if (!(ISSIGVALID(mode->relsig) && - ISSIGVALID(mode->acqsig) && - (mode->frsig == 0 || ISSIGVALID(mode->frsig)))) { + if (!(_SIG_VALID(mode->relsig) && + _SIG_VALID(mode->acqsig) && + (mode->frsig == 0 || _SIG_VALID(mode->frsig)))) { DPRINTF(5, "error EINVAL\n"); return (EINVAL); } @@ -3171,6 +3200,10 @@ vt_upgrade(struct vt_device *vd) /* For existing console window. */ EVENTHANDLER_REGISTER(shutdown_pre_sync, vt_window_switch, vw, SHUTDOWN_PRI_DEFAULT); +#ifdef DEV_SPLASH + EVENTHANDLER_REGISTER(shutdown_pre_sync, + vt_shutdown_splash, vw, SHUTDOWN_PRI_DEFAULT + 1); +#endif } } } diff --git a/sys/dev/wg/if_wg.c b/sys/dev/wg/if_wg.c index 17aedee0e6b0..611314883643 100644 --- a/sys/dev/wg/if_wg.c +++ b/sys/dev/wg/if_wg.c @@ -3033,8 +3033,8 @@ wg_clone_create(struct if_clone *ifc, char *name, size_t len, if_attach(ifp); bpfattach(ifp, DLT_NULL, sizeof(uint32_t)); #ifdef INET6 - ND_IFINFO(ifp)->flags &= ~ND6_IFF_AUTO_LINKLOCAL; - ND_IFINFO(ifp)->flags |= ND6_IFF_NO_DAD; + if_getinet6(ifp)->nd_flags &= ~ND6_IFF_AUTO_LINKLOCAL; + if_getinet6(ifp)->nd_flags |= ND6_IFF_NO_DAD; #endif sx_xlock(&wg_sx); LIST_INSERT_HEAD(&wg_list, sc, sc_entry); diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c index 471700ca9f5c..f6039c5bb790 100644 --- a/sys/dev/wpi/if_wpi.c +++ b/sys/dev/wpi/if_wpi.c @@ -2917,7 +2917,8 @@ wpi_tx_data(struct wpi_softc *sc, struct mbuf *m, struct ieee80211_node *ni) break; } - memcpy(tx->key, k->wk_key, k->wk_keylen); + memcpy(tx->key, ieee80211_crypto_get_key_data(k), + ieee80211_crypto_get_key_len(k)); } if (wh->i_fc[1] & IEEE80211_FC1_MORE_FRAG) { @@ -3031,7 +3032,8 @@ wpi_tx_data_raw(struct wpi_softc *sc, struct mbuf *m, break; } - memcpy(tx->key, k->wk_key, k->wk_keylen); + memcpy(tx->key, ieee80211_crypto_get_key_data(k), + ieee80211_crypto_get_key_len(k)); } tx->len = htole16(totlen); @@ -4627,7 +4629,8 @@ wpi_load_key(struct ieee80211_node *ni, const struct ieee80211_key *k) node.control = WPI_NODE_UPDATE; node.flags = WPI_FLAG_KEY_SET; node.kflags = htole16(kflags); - memcpy(node.key, k->wk_key, k->wk_keylen); + memcpy(node.key, ieee80211_crypto_get_key_data(k), + ieee80211_crypto_get_key_len(k)); again: DPRINTF(sc, WPI_DEBUG_KEY, "%s: setting %s key id %d for node %d (%s)\n", __func__, diff --git a/sys/dev/xdma/xdma.h b/sys/dev/xdma/xdma.h index 40f6ea8f6f98..2e1c0d64ee46 100644 --- a/sys/dev/xdma/xdma.h +++ b/sys/dev/xdma/xdma.h @@ -93,7 +93,7 @@ struct xchan_buf { bus_dmamap_t map; uint32_t nsegs; uint32_t nsegs_left; - vm_offset_t vaddr; + void *vaddr; vm_offset_t paddr; vm_size_t size; }; diff --git a/sys/dev/xdma/xdma_sg.c b/sys/dev/xdma/xdma_sg.c index ccf721e3c16c..c102e9b9f456 100644 --- a/sys/dev/xdma/xdma_sg.c +++ b/sys/dev/xdma/xdma_sg.c @@ -75,9 +75,9 @@ xchan_bufs_free_reserved(xdma_channel_t *xchan) xr = &xchan->xr_mem[i]; size = xr->buf.size; if (xr->buf.vaddr) { - pmap_kremove_device(xr->buf.vaddr, size); + pmap_kremove_device((vm_offset_t)xr->buf.vaddr, size); kva_free(xr->buf.vaddr, size); - xr->buf.vaddr = 0; + xr->buf.vaddr = NULL; } if (xr->buf.paddr) { vmem_free(xchan->vmem, xr->buf.paddr, size); @@ -115,13 +115,13 @@ xchan_bufs_alloc_reserved(xdma_channel_t *xchan) xr->buf.size = size; xr->buf.paddr = addr; xr->buf.vaddr = kva_alloc(size); - if (xr->buf.vaddr == 0) { + if (xr->buf.vaddr == NULL) { device_printf(xdma->dev, "%s: Can't allocate KVA\n", __func__); xchan_bufs_free_reserved(xchan); return (ENOMEM); } - pmap_kenter_device(xr->buf.vaddr, size, addr); + pmap_kenter_device((vm_offset_t)xr->buf.vaddr, size, addr); } return (0); @@ -346,7 +346,7 @@ xchan_seg_done(xdma_channel_t *xchan, if (xr->req_type == XR_TYPE_MBUF && xr->direction == XDMA_DEV_TO_MEM) m_copyback(xr->m, 0, st->transferred, - (void *)xr->buf.vaddr); + xr->buf.vaddr); } else if (xchan->caps & XCHAN_CAP_IOMMU) { if (xr->direction == XDMA_MEM_TO_DEV) addr = xr->src_addr; @@ -500,7 +500,7 @@ _xdma_load_data(xdma_channel_t *xchan, struct xdma_request *xr, if (xchan->caps & XCHAN_CAP_BOUNCE) { if (xr->direction == XDMA_MEM_TO_DEV) m_copydata(m, 0, m->m_pkthdr.len, - (void *)xr->buf.vaddr); + xr->buf.vaddr); seg[0].ds_addr = (bus_addr_t)xr->buf.paddr; } else if (xchan->caps & XCHAN_CAP_IOMMU) { addr = mtod(m, bus_addr_t); diff --git a/sys/dev/xen/acpi/xen-acpi.c b/sys/dev/xen/acpi/xen-acpi.c new file mode 100644 index 000000000000..1e46883e2c86 --- /dev/null +++ b/sys/dev/xen/acpi/xen-acpi.c @@ -0,0 +1,75 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2026 Citrix Systems R&D + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#include "opt_acpi.h" +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/kernel.h> +#include <sys/kobj.h> + +#include <machine/_inttypes.h> + +#include <contrib/dev/acpica/include/acpi.h> +#include <contrib/dev/acpica/include/accommon.h> + +#include <dev/acpica/acpivar.h> + +#include <xen/xen-os.h> + +static int prepare_sleep_state(uint8_t state, uint32_t a, uint32_t b, bool ext) +{ + struct xen_platform_op op = { + .cmd = XENPF_enter_acpi_sleep, + .interface_version = XENPF_INTERFACE_VERSION, + .u.enter_acpi_sleep.val_a = a, + .u.enter_acpi_sleep.val_b = b, + .u.enter_acpi_sleep.sleep_state = state, + .u.enter_acpi_sleep.flags = + ext ? XENPF_ACPI_SLEEP_EXTENDED : 0, + }; + int error; + + error = HYPERVISOR_platform_op(&op); + if (error) + printf("Xen notify ACPI sleep failed - " + "State %#x A %#x B %#x: %d\n", state, a, b, error); + + return (error ? error : 1); +} + +static int init_xen_acpi_sleep(void *arg) +{ + if (!xen_initial_domain()) + return (0); + + acpi_set_prepare_sleep(&prepare_sleep_state); + return (0); +} + +SYSINIT(xen_sleep, SI_SUB_CONFIGURE, SI_ORDER_ANY, init_xen_acpi_sleep, NULL); diff --git a/sys/dev/xen/gntdev/gntdev.c b/sys/dev/xen/gntdev/gntdev.c index e3bc1ecf35ab..7824c283d6ba 100644 --- a/sys/dev/xen/gntdev/gntdev.c +++ b/sys/dev/xen/gntdev/gntdev.c @@ -830,9 +830,9 @@ notify(struct notify_data *notify, vm_page_t page) uint64_t offset; offset = notify->index & PAGE_MASK; - mem = (uint8_t *)pmap_quick_enter_page(page); + mem = pmap_quick_enter_page(page); mem[offset] = 0; - pmap_quick_remove_page((vm_offset_t)mem); + pmap_quick_remove_page(mem); } if (notify->action & UNMAP_NOTIFY_SEND_EVENT) { xen_intr_signal(notify->notify_evtchn_handle); diff --git a/sys/dev/xilinx/if_xae.c b/sys/dev/xilinx/if_xae.c index 435902dc3c10..ee444749e9fc 100644 --- a/sys/dev/xilinx/if_xae.c +++ b/sys/dev/xilinx/if_xae.c @@ -1357,7 +1357,7 @@ static device_method_t xae_methods[] = { DEVMETHOD(miibus_readreg, xae_miibus_read_reg), DEVMETHOD(miibus_writereg, xae_miibus_write_reg), DEVMETHOD(miibus_statchg, xae_miibus_statchg), - { 0, 0 } + DEVMETHOD_END }; driver_t xae_driver = { |
