aboutsummaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpica/acpi.c9
-rw-r--r--sys/dev/acpica/acpi_pci.c12
-rw-r--r--sys/dev/acpica/acpi_powerres.c58
-rw-r--r--sys/dev/acpica/acpivar.h10
-rw-r--r--sys/dev/amdgpio/amdgpio.c3
-rw-r--r--sys/dev/bhnd/cores/chipc/chipc_gpio.c4
-rw-r--r--sys/dev/ftgpio/ftgpio.c3
-rw-r--r--sys/dev/gpio/acpi_gpiobus.c3
-rw-r--r--sys/dev/gpio/bytgpio.c3
-rw-r--r--sys/dev/gpio/chvgpio.c3
-rw-r--r--sys/dev/gpio/dwgpio/dwgpio.c3
-rw-r--r--sys/dev/gpio/gpiobus.c18
-rw-r--r--sys/dev/gpio/gpiobusvar.h1
-rw-r--r--sys/dev/gpio/pl061.c3
-rw-r--r--sys/dev/gpio/qoriq_gpio.c3
-rw-r--r--sys/dev/iicbus/gpio/pcf8574.c7
-rw-r--r--sys/dev/iicbus/gpio/tca64xx.c7
-rw-r--r--sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c4
-rw-r--r--sys/dev/nctgpio/nctgpio.c3
-rw-r--r--sys/dev/null/null.c48
-rw-r--r--sys/dev/p2sb/lewisburg_gpio.c3
-rw-r--r--sys/dev/pci/pci.c5
-rw-r--r--sys/dev/pci/pcivar.h39
-rw-r--r--sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c3
-rw-r--r--sys/dev/rccgpio/rccgpio.c3
-rw-r--r--sys/dev/uart/uart_cpu_acpi.c20
-rw-r--r--sys/dev/uart/uart_cpu_acpi.h17
-rw-r--r--sys/dev/uart/uart_dev_ns8250.c42
-rw-r--r--sys/dev/uart/uart_dev_pl011.c16
-rw-r--r--sys/dev/usb/misc/cp2112.c5
-rw-r--r--sys/dev/usb/net/if_ipheth.c218
-rw-r--r--sys/dev/usb/net/if_iphethvar.h21
-rw-r--r--sys/dev/watchdog/watchdog.c212
33 files changed, 544 insertions, 265 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index f2ff1d59ccc7..a2159b12876f 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -2139,12 +2139,13 @@ acpi_set_powerstate(device_t child, int state)
status = acpi_pwr_switch_consumer(h, state);
if (ACPI_SUCCESS(status)) {
if (bootverbose)
- device_printf(child, "set ACPI power state D%d on %s\n",
- state, acpi_name(h));
+ device_printf(child, "set ACPI power state %s on %s\n",
+ acpi_d_state_to_str(state), acpi_name(h));
} else if (status != AE_NOT_FOUND)
device_printf(child,
- "failed to set ACPI power state D%d on %s: %s\n", state,
- acpi_name(h), AcpiFormatException(status));
+ "failed to set ACPI power state %s on %s: %s\n",
+ acpi_d_state_to_str(state), acpi_name(h),
+ AcpiFormatException(status));
return (0);
}
diff --git a/sys/dev/acpica/acpi_pci.c b/sys/dev/acpica/acpi_pci.c
index 646295f9eecc..1912350bbc48 100644
--- a/sys/dev/acpica/acpi_pci.c
+++ b/sys/dev/acpica/acpi_pci.c
@@ -53,9 +53,6 @@
#include <dev/iommu/iommu.h>
-#include "pcib_if.h"
-#include "pci_if.h"
-
/* Hooks for the ACPI CA debugging infrastructure. */
#define _COMPONENT ACPI_BUS
ACPI_MODULE_NAME("PCI")
@@ -266,12 +263,13 @@ acpi_pci_set_powerstate_method(device_t dev, device_t child, int state)
status = acpi_pwr_switch_consumer(h, state);
if (ACPI_SUCCESS(status)) {
if (bootverbose)
- device_printf(dev, "set ACPI power state D%d on %s\n",
- state, acpi_name(h));
+ device_printf(dev, "set ACPI power state %s on %s\n",
+ acpi_d_state_to_str(state), acpi_name(h));
} else if (status != AE_NOT_FOUND)
device_printf(dev,
- "failed to set ACPI power state D%d on %s: %s\n",
- state, acpi_name(h), AcpiFormatException(status));
+ "failed to set ACPI power state %s on %s: %s\n",
+ acpi_d_state_to_str(state), acpi_name(h),
+ AcpiFormatException(status));
if (old_state > state && pci_do_power_resume)
error = pci_set_powerstate_method(dev, child, state);
diff --git a/sys/dev/acpica/acpi_powerres.c b/sys/dev/acpica/acpi_powerres.c
index 0f2a25b1d02b..29d1690f1bdd 100644
--- a/sys/dev/acpica/acpi_powerres.c
+++ b/sys/dev/acpica/acpi_powerres.c
@@ -299,7 +299,7 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
ACPI_BUFFER reslist_buffer;
ACPI_OBJECT *reslist_object;
ACPI_STATUS status;
- char *method_name, *reslist_name;
+ char *method_name, *reslist_name = NULL;
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
@@ -318,9 +318,26 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
panic("acpi added power consumer but can't find it");
}
- /* Check for valid transitions. We can only go to D0 from D3. */
+ /* Stop here if we're already at the target D-state. */
+ if (pc->ac_state == state) {
+ status = AE_OK;
+ goto out;
+ }
+
+ /*
+ * Check for valid transitions. From D3hot or D3cold, we can only go to D0.
+ * The exception to this is going from D3hot to D3cold or the other way
+ * around. This is because they both use _PS3, so the only difference when
+ * doing these transitions is whether or not the power resources for _PR3
+ * are on for devices which support D3cold, and turning these power
+ * resources on/off is always perfectly fine (ACPI 7.3.11).
+ */
status = AE_BAD_PARAMETER;
- if (pc->ac_state == ACPI_STATE_D3 && state != ACPI_STATE_D0)
+ if (pc->ac_state == ACPI_STATE_D3_HOT && state != ACPI_STATE_D0 &&
+ state != ACPI_STATE_D3_COLD)
+ goto out;
+ if (pc->ac_state == ACPI_STATE_D3_COLD && state != ACPI_STATE_D0 &&
+ state != ACPI_STATE_D3_HOT)
goto out;
/* Find transition mechanism(s) */
@@ -337,15 +354,20 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
method_name = "_PS2";
reslist_name = "_PR2";
break;
- case ACPI_STATE_D3:
+ case ACPI_STATE_D3_HOT:
method_name = "_PS3";
reslist_name = "_PR3";
break;
+ case ACPI_STATE_D3_COLD:
+ method_name = "_PS3";
+ reslist_name = NULL;
+ break;
default:
goto out;
}
- ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "setup to switch %s D%d -> D%d\n",
- acpi_name(consumer), pc->ac_state, state));
+ ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "setup to switch %s %s -> %s\n",
+ acpi_name(consumer), acpi_d_state_to_str(pc->ac_state),
+ acpi_d_state_to_str(state)));
/*
* Verify that this state is supported, ie. one of method or
@@ -359,7 +381,8 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
*/
if (ACPI_FAILURE(AcpiGetHandle(consumer, method_name, &method_handle)))
method_handle = NULL;
- if (ACPI_FAILURE(AcpiGetHandle(consumer, reslist_name, &reslist_handle)))
+ if (reslist_name == NULL ||
+ ACPI_FAILURE(AcpiGetHandle(consumer, reslist_name, &reslist_handle)))
reslist_handle = NULL;
if (reslist_handle == NULL && method_handle == NULL) {
if (state == ACPI_STATE_D0) {
@@ -367,9 +390,12 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
status = AE_OK;
goto out;
}
- if (state != ACPI_STATE_D3) {
+ if (state == ACPI_STATE_D3_COLD)
+ state = ACPI_STATE_D3_HOT;
+ if (state != ACPI_STATE_D3_HOT) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
- "attempt to set unsupported state D%d\n", state));
+ "attempt to set unsupported state %s\n",
+ acpi_d_state_to_str(state)));
goto out;
}
@@ -380,21 +406,23 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
if (ACPI_FAILURE(AcpiGetHandle(consumer, "_PR0", &pr0_handle))) {
status = AE_NOT_FOUND;
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
- "device missing _PR0 (desired state was D%d)\n", state));
+ "device missing _PR0 (desired state was %s)\n",
+ acpi_d_state_to_str(state)));
goto out;
}
reslist_buffer.Length = ACPI_ALLOCATE_BUFFER;
status = AcpiEvaluateObject(pr0_handle, NULL, NULL, &reslist_buffer);
if (ACPI_FAILURE(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
- "can't evaluate _PR0 for device %s, state D%d\n",
- acpi_name(consumer), state));
+ "can't evaluate _PR0 for device %s, state %s\n",
+ acpi_name(consumer), acpi_d_state_to_str(state)));
goto out;
}
reslist_object = (ACPI_OBJECT *)reslist_buffer.Pointer;
if (!ACPI_PKG_VALID(reslist_object, 1)) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
- "invalid package object for state D%d\n", state));
+ "invalid package object for state %s\n",
+ acpi_d_state_to_str(state)));
status = AE_TYPE;
goto out;
}
@@ -450,8 +478,8 @@ acpi_pwr_switch_consumer(ACPI_HANDLE consumer, int state)
*/
if (ACPI_FAILURE(status = acpi_pwr_switch_power())) {
ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS,
- "failed to switch resources from %s to D%d\n",
- acpi_name(consumer), state));
+ "failed to switch resources from %s to %s\n",
+ acpi_name(consumer), acpi_d_state_to_str(state)));
/* XXX is this appropriate? Should we return to previous state? */
goto out;
diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h
index 106ec9038820..6887f080311d 100644
--- a/sys/dev/acpica/acpivar.h
+++ b/sys/dev/acpica/acpivar.h
@@ -517,6 +517,16 @@ acpi_get_verbose(struct acpi_softc *sc)
return (0);
}
+static __inline const char *
+acpi_d_state_to_str(int state)
+{
+ const char *strs[ACPI_D_STATE_COUNT] = {"D0", "D1", "D2", "D3hot",
+ "D3cold"};
+
+ MPASS(state >= ACPI_STATE_D0 && state <= ACPI_D_STATES_MAX);
+ return (strs[state]);
+}
+
char *acpi_name(ACPI_HANDLE handle);
int acpi_avoid(ACPI_HANDLE handle);
int acpi_disabled(char *subsys);
diff --git a/sys/dev/amdgpio/amdgpio.c b/sys/dev/amdgpio/amdgpio.c
index f39006d95805..2bd455c612b8 100644
--- a/sys/dev/amdgpio/amdgpio.c
+++ b/sys/dev/amdgpio/amdgpio.c
@@ -408,12 +408,13 @@ amdgpio_attach(device_t dev)
GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
}
- sc->sc_busdev = gpiobus_attach_bus(dev);
+ sc->sc_busdev = gpiobus_add_bus(dev);
if (sc->sc_busdev == NULL) {
device_printf(dev, "could not attach gpiobus\n");
goto err_bus;
}
+ bus_attach_children(dev);
return (0);
err_bus:
diff --git a/sys/dev/bhnd/cores/chipc/chipc_gpio.c b/sys/dev/bhnd/cores/chipc/chipc_gpio.c
index a110bdda5fa7..429de0fc1fd8 100644
--- a/sys/dev/bhnd/cores/chipc/chipc_gpio.c
+++ b/sys/dev/bhnd/cores/chipc/chipc_gpio.c
@@ -173,11 +173,13 @@ chipc_gpio_attach(device_t dev)
if (CC_GPIO_QUIRK(sc, NO_GPIOC)) {
sc->gpiobus = NULL;
} else {
- if ((sc->gpiobus = gpiobus_attach_bus(dev)) == NULL) {
+ if ((sc->gpiobus = gpiobus_add_bus(dev)) == NULL) {
device_printf(dev, "failed to attach gpiobus\n");
error = ENXIO;
goto failed;
}
+
+ bus_attach_children(dev);
}
/* Register as the bus GPIO provider */
diff --git a/sys/dev/ftgpio/ftgpio.c b/sys/dev/ftgpio/ftgpio.c
index 7acfdd5b900e..68787b54bb16 100644
--- a/sys/dev/ftgpio/ftgpio.c
+++ b/sys/dev/ftgpio/ftgpio.c
@@ -398,12 +398,13 @@ ftgpio_attach(device_t dev)
FTGPIO_VERBOSE_PRINTF(sc->dev, "groups GPIO1..GPIO6 enabled\n");
GPIO_UNLOCK(sc);
- sc->busdev = gpiobus_attach_bus(dev);
+ sc->busdev = gpiobus_add_bus(dev);
if (sc->busdev == NULL) {
GPIO_LOCK_DESTROY(sc);
return (ENXIO);
}
+ bus_attach_children(dev);
return (0);
}
diff --git a/sys/dev/gpio/acpi_gpiobus.c b/sys/dev/gpio/acpi_gpiobus.c
index 94f4e5771266..170f23615416 100644
--- a/sys/dev/gpio/acpi_gpiobus.c
+++ b/sys/dev/gpio/acpi_gpiobus.c
@@ -383,7 +383,8 @@ acpi_gpiobus_detach(device_t dev)
}
static int
-acpi_gpiobus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+acpi_gpiobus_read_ivar(device_t dev, device_t child, int which,
+ uintptr_t *result)
{
struct acpi_gpiobus_ivar *devi = device_get_ivars(child);
diff --git a/sys/dev/gpio/bytgpio.c b/sys/dev/gpio/bytgpio.c
index f7b2a73ec6cb..5d685c155a03 100644
--- a/sys/dev/gpio/bytgpio.c
+++ b/sys/dev/gpio/bytgpio.c
@@ -608,7 +608,7 @@ bytgpio_attach(device_t dev)
sc->sc_pad_funcs[pin] = val & BYTGPIO_PCONF0_FUNC_MASK;
}
- sc->sc_busdev = gpiobus_attach_bus(dev);
+ sc->sc_busdev = gpiobus_add_bus(dev);
if (sc->sc_busdev == NULL) {
BYTGPIO_LOCK_DESTROY(sc);
bus_release_resource(dev, SYS_RES_MEMORY,
@@ -616,6 +616,7 @@ bytgpio_attach(device_t dev)
return (ENXIO);
}
+ bus_attach_children(dev);
return (0);
error:
diff --git a/sys/dev/gpio/chvgpio.c b/sys/dev/gpio/chvgpio.c
index 199ad4d6f373..3273aad9242b 100644
--- a/sys/dev/gpio/chvgpio.c
+++ b/sys/dev/gpio/chvgpio.c
@@ -441,7 +441,7 @@ chvgpio_attach(device_t dev)
bus_write_4(sc->sc_mem_res, CHVGPIO_INTERRUPT_MASK, 0);
bus_write_4(sc->sc_mem_res, CHVGPIO_INTERRUPT_STATUS, 0xffff);
- sc->sc_busdev = gpiobus_attach_bus(dev);
+ sc->sc_busdev = gpiobus_add_bus(dev);
if (sc->sc_busdev == NULL) {
CHVGPIO_LOCK_DESTROY(sc);
bus_release_resource(dev, SYS_RES_MEMORY,
@@ -451,6 +451,7 @@ chvgpio_attach(device_t dev)
return (ENXIO);
}
+ bus_attach_children(dev);
return (0);
}
diff --git a/sys/dev/gpio/dwgpio/dwgpio.c b/sys/dev/gpio/dwgpio/dwgpio.c
index 5acb99ca591e..3908113d5fd4 100644
--- a/sys/dev/gpio/dwgpio/dwgpio.c
+++ b/sys/dev/gpio/dwgpio/dwgpio.c
@@ -167,12 +167,13 @@ dwgpio_attach(device_t dev)
snprintf(sc->gpio_pins[i].gp_name, GPIOMAXNAME,
"dwgpio%d.%d", device_get_unit(dev), i);
}
- sc->busdev = gpiobus_attach_bus(dev);
+ sc->busdev = gpiobus_add_bus(dev);
if (sc->busdev == NULL) {
mtx_destroy(&sc->sc_mtx);
return (ENXIO);
}
+ bus_attach_children(dev);
return (0);
}
diff --git a/sys/dev/gpio/gpiobus.c b/sys/dev/gpio/gpiobus.c
index 764bcb7e6ee8..c25c41f43042 100644
--- a/sys/dev/gpio/gpiobus.c
+++ b/sys/dev/gpio/gpiobus.c
@@ -330,24 +330,6 @@ gpiobus_add_bus(device_t dev)
return (busdev);
}
-/*
- * Attach a gpiobus child.
- * Note that the controller is expected
- * to be fully initialized at this point.
- */
-device_t
-gpiobus_attach_bus(device_t dev)
-{
- device_t busdev;
-
- busdev = gpiobus_add_bus(dev);
- if (busdev == NULL)
- return (NULL);
-
- bus_attach_children(dev);
- return (busdev);
-}
-
int
gpiobus_detach_bus(device_t dev)
{
diff --git a/sys/dev/gpio/gpiobusvar.h b/sys/dev/gpio/gpiobusvar.h
index 7f504236a774..0528efe45525 100644
--- a/sys/dev/gpio/gpiobusvar.h
+++ b/sys/dev/gpio/gpiobusvar.h
@@ -171,7 +171,6 @@ struct resource *gpio_alloc_intr_resource(device_t consumer_dev, int *rid,
int gpio_check_flags(uint32_t, uint32_t);
device_t gpiobus_add_bus(device_t);
-device_t gpiobus_attach_bus(device_t);
int gpiobus_detach_bus(device_t);
#endif /* __GPIOBUS_H__ */
diff --git a/sys/dev/gpio/pl061.c b/sys/dev/gpio/pl061.c
index 87d4310a6396..32109e5982bc 100644
--- a/sys/dev/gpio/pl061.c
+++ b/sys/dev/gpio/pl061.c
@@ -495,13 +495,14 @@ pl061_attach(device_t dev)
goto free_isrc;
}
- sc->sc_busdev = gpiobus_attach_bus(dev);
+ sc->sc_busdev = gpiobus_add_bus(dev);
if (sc->sc_busdev == NULL) {
device_printf(dev, "couldn't attach gpio bus\n");
PL061_LOCK_DESTROY(sc);
goto free_isrc;
}
+ bus_attach_children(dev);
return (0);
free_isrc:
diff --git a/sys/dev/gpio/qoriq_gpio.c b/sys/dev/gpio/qoriq_gpio.c
index 8b44cd256c79..d11868a23751 100644
--- a/sys/dev/gpio/qoriq_gpio.c
+++ b/sys/dev/gpio/qoriq_gpio.c
@@ -379,12 +379,13 @@ qoriq_gpio_attach(device_t dev)
OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
- sc->busdev = gpiobus_attach_bus(dev);
+ sc->busdev = gpiobus_add_bus(dev);
if (sc->busdev == NULL) {
qoriq_gpio_detach(dev);
return (ENOMEM);
}
+ bus_attach_children(dev);
return (0);
}
diff --git a/sys/dev/iicbus/gpio/pcf8574.c b/sys/dev/iicbus/gpio/pcf8574.c
index ab6e2bc07d1f..bf60dec67557 100644
--- a/sys/dev/iicbus/gpio/pcf8574.c
+++ b/sys/dev/iicbus/gpio/pcf8574.c
@@ -142,12 +142,13 @@ pcf8574_attach(device_t dev)
(void)pcf8574_write(sc, 0xff);
sx_init(&sc->lock, "pcf8574");
- sc->busdev = gpiobus_attach_bus(dev);
+ sc->busdev = gpiobus_add_bus(dev);
if (sc->busdev == NULL) {
device_printf(dev, "Could not create busdev child\n");
sx_destroy(&sc->lock);
return (ENXIO);
}
+ bus_attach_children(dev);
return (0);
}
@@ -158,9 +159,7 @@ pcf8574_detach(device_t dev)
sc = device_get_softc(dev);
- if (sc->busdev != NULL)
- gpiobus_detach_bus(sc->busdev);
-
+ gpiobus_detach_bus(dev);
sx_destroy(&sc->lock);
return (0);
}
diff --git a/sys/dev/iicbus/gpio/tca64xx.c b/sys/dev/iicbus/gpio/tca64xx.c
index cd011ae9be75..ab8fedd3f8fd 100644
--- a/sys/dev/iicbus/gpio/tca64xx.c
+++ b/sys/dev/iicbus/gpio/tca64xx.c
@@ -262,7 +262,7 @@ tca64xx_attach(device_t dev)
mtx_init(&sc->mtx, "tca64xx gpio", "gpio", MTX_DEF);
OF_device_register_xref(OF_xref_from_node(ofw_bus_get_node(dev)), dev);
- sc->busdev = gpiobus_attach_bus(dev);
+ sc->busdev = gpiobus_add_bus(dev);
if (sc->busdev == NULL) {
device_printf(dev, "Could not create busdev child\n");
return (ENXIO);
@@ -281,6 +281,7 @@ tca64xx_attach(device_t dev)
}
#endif
+ bus_attach_children(dev);
return (0);
}
@@ -291,9 +292,7 @@ tca64xx_detach(device_t dev)
sc = device_get_softc(dev);
- if (sc->busdev != NULL)
- gpiobus_detach_bus(sc->busdev);
-
+ gpiobus_detach_bus(dev);
mtx_destroy(&sc->mtx);
return (0);
diff --git a/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c b/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
index 6e24395b5577..c45f02cdaf42 100644
--- a/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
+++ b/sys/dev/mlx5/mlx5_en/mlx5_en_flow_table.c
@@ -1783,8 +1783,8 @@ mlx5e_add_vxlan_rule(struct mlx5e_priv *priv, sa_family_t family, u_int port)
el->refcount++;
if (el->installed)
return (0);
- }
- el = mlx5e_vxlan_alloc_db_el(priv, proto, port);
+ } else
+ el = mlx5e_vxlan_alloc_db_el(priv, proto, port);
if ((if_getcapenable(priv->ifp) & IFCAP_VXLAN_HWCSUM) != 0) {
err = mlx5e_add_vxlan_rule_from_db(priv, el);
diff --git a/sys/dev/nctgpio/nctgpio.c b/sys/dev/nctgpio/nctgpio.c
index 75ea1fbdba17..ddc2ceef7dfb 100644
--- a/sys/dev/nctgpio/nctgpio.c
+++ b/sys/dev/nctgpio/nctgpio.c
@@ -1258,13 +1258,14 @@ nct_attach(device_t dev)
GPIO_UNLOCK(sc);
- sc->busdev = gpiobus_attach_bus(dev);
+ sc->busdev = gpiobus_add_bus(dev);
if (sc->busdev == NULL) {
device_printf(dev, "failed to attach to gpiobus\n");
GPIO_LOCK_DESTROY(sc);
return (ENXIO);
}
+ bus_attach_children(dev);
return (0);
}
diff --git a/sys/dev/null/null.c b/sys/dev/null/null.c
index 7ffc618e63ee..8525eb9543c3 100644
--- a/sys/dev/null/null.c
+++ b/sys/dev/null/null.c
@@ -4,6 +4,7 @@
* Copyright (c) 2000 Mark R. V. Murray & Jeroen C. van Gelderen
* Copyright (c) 2001-2004 Mark R. V. Murray
* Copyright (c) 2014 Eitan Adler
+ * Copyright (c) 2025 Pietro Cerutti
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -39,6 +40,7 @@
#include <sys/disk.h>
#include <sys/bus.h>
#include <sys/filio.h>
+#include <sys/event.h>
#include <machine/bus.h>
#include <machine/vmparam.h>
@@ -53,12 +55,26 @@ static d_write_t null_write;
static d_ioctl_t null_ioctl;
static d_ioctl_t zero_ioctl;
static d_read_t zero_read;
+static d_kqfilter_t kqfilter;
+static int one_ev(struct knote *kn, long hint);
+static int zero_ev(struct knote *kn, long hint);
+
+static const struct filterops one_fop = {
+ .f_isfd = 1,
+ .f_event = one_ev
+};
+
+static const struct filterops zero_fop = {
+ .f_isfd = 1,
+ .f_event = zero_ev
+};
static struct cdevsw full_cdevsw = {
.d_version = D_VERSION,
.d_read = zero_read,
.d_write = full_write,
.d_ioctl = zero_ioctl,
+ .d_kqfilter = kqfilter,
.d_name = "full",
};
@@ -67,6 +83,7 @@ static struct cdevsw null_cdevsw = {
.d_read = (d_read_t *)nullop,
.d_write = null_write,
.d_ioctl = null_ioctl,
+ .d_kqfilter = kqfilter,
.d_name = "null",
};
@@ -75,6 +92,7 @@ static struct cdevsw zero_cdevsw = {
.d_read = zero_read,
.d_write = null_write,
.d_ioctl = zero_ioctl,
+ .d_kqfilter = kqfilter,
.d_name = "zero",
.d_flags = D_MMAP_ANON,
};
@@ -197,5 +215,35 @@ null_modevent(module_t mod __unused, int type, void *data __unused)
return (0);
}
+static int
+one_ev(struct knote *kn, long hint)
+{
+
+ return (1);
+}
+
+static int
+zero_ev(struct knote *kn, long hint)
+{
+
+ return (0);
+}
+
+static int
+kqfilter(struct cdev *dev, struct knote *kn)
+{
+
+ switch (kn->kn_filter) {
+ case EVFILT_READ:
+ kn->kn_fop = dev->si_devsw == &null_cdevsw ? &zero_fop : &one_fop;
+ return (0);
+ case EVFILT_WRITE:
+ kn->kn_fop = dev->si_devsw == &full_cdevsw ? &zero_fop : &one_fop;
+ return (0);
+ default:
+ return (EOPNOTSUPP);
+ }
+}
+
DEV_MODULE(null, null_modevent, NULL);
MODULE_VERSION(null, 1);
diff --git a/sys/dev/p2sb/lewisburg_gpio.c b/sys/dev/p2sb/lewisburg_gpio.c
index b45d7767602c..3be777ab9524 100644
--- a/sys/dev/p2sb/lewisburg_gpio.c
+++ b/sys/dev/p2sb/lewisburg_gpio.c
@@ -217,10 +217,11 @@ lbggpio_attach(device_t dev)
}
/* support gpio */
- sc->sc_busdev = gpiobus_attach_bus(dev);
+ sc->sc_busdev = gpiobus_add_bus(dev);
if (sc->sc_busdev == NULL)
return (ENXIO);
+ bus_attach_children(dev);
return (0);
}
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index f94438cda041..9e43a4c1909f 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -2896,8 +2896,9 @@ pci_set_powerstate_method(device_t dev, device_t child, int state)
}
if (bootverbose)
- pci_printf(cfg, "Transition from D%d to D%d\n", oldstate,
- state);
+ pci_printf(cfg, "Transition from %s to %s\n",
+ pci_powerstate_to_str(oldstate),
+ pci_powerstate_to_str(state));
PCI_WRITE_CONFIG(dev, child, cfg->pp.pp_location + PCIR_POWER_STATUS,
status, 2);
diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index d1b7d28eae91..4abb5e977346 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/pci/pcivar.h
@@ -497,24 +497,39 @@ pci_is_vga_memory_range(rman_res_t start, rman_res_t end)
/*
* PCI power states are as defined by ACPI:
*
- * D0 State in which device is on and running. It is receiving full
- * power from the system and delivering full functionality to the user.
- * D1 Class-specific low-power state in which device context may or may not
- * be lost. Buses in D1 cannot do anything to the bus that would force
- * devices on that bus to lose context.
- * D2 Class-specific low-power state in which device context may or may
- * not be lost. Attains greater power savings than D1. Buses in D2
- * can cause devices on that bus to lose some context. Devices in D2
- * must be prepared for the bus to be in D2 or higher.
- * D3 State in which the device is off and not running. Device context is
- * lost. Power can be removed from the device.
+ * D0 State in which device is on and running. It is receiving full
+ * power from the system and delivering full functionality to the user.
+ * D1 Class-specific low-power state in which device context may or may not
+ * be lost. Buses in D1 cannot do anything to the bus that would force
+ * devices on that bus to lose context.
+ * D2 Class-specific low-power state in which device context may or may
+ * not be lost. Attains greater power savings than D1. Buses in D2
+ * can cause devices on that bus to lose some context. Devices in D2
+ * must be prepared for the bus to be in D2 or higher.
+ * D3hot State in which the device is off and not running. Device context is
+ * lost. Power can be removed from the device.
+ * D3cold Same as D3hot, but power has been removed from the device.
*/
#define PCI_POWERSTATE_D0 0
#define PCI_POWERSTATE_D1 1
#define PCI_POWERSTATE_D2 2
-#define PCI_POWERSTATE_D3 3
+#define PCI_POWERSTATE_D3_HOT 3
+#define PCI_POWERSTATE_D3_COLD 4
+#define PCI_POWERSTATE_D3 PCI_POWERSTATE_D3_COLD
+#define PCI_POWERSTATE_MAX PCI_POWERSTATE_D3_COLD
+#define PCI_POWERSTATE_COUNT 5
#define PCI_POWERSTATE_UNKNOWN -1
+static __inline const char *
+pci_powerstate_to_str(int state)
+{
+ const char *strs[PCI_POWERSTATE_COUNT] = {"D0", "D1", "D2", "D3hot",
+ "D3cold"};
+
+ MPASS(state >= PCI_POWERSTATE_D0 && state <= PCI_POWERSTATE_MAX);
+ return (strs[state]);
+}
+
static __inline int
pci_set_powerstate(device_t dev, int state)
{
diff --git a/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c b/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c
index 2d390cd449af..50f54b896748 100644
--- a/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c
+++ b/sys/dev/qcom_tlmm/qcom_tlmm_ipq4018.c
@@ -346,13 +346,14 @@ qcom_tlmm_ipq4018_attach(device_t dev)
fdt_pinctrl_register(dev, NULL);
fdt_pinctrl_configure_by_name(dev, "default");
- sc->busdev = gpiobus_attach_bus(dev);
+ 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);
}
diff --git a/sys/dev/rccgpio/rccgpio.c b/sys/dev/rccgpio/rccgpio.c
index b2b775b879ad..dafd0b511fa9 100644
--- a/sys/dev/rccgpio/rccgpio.c
+++ b/sys/dev/rccgpio/rccgpio.c
@@ -308,7 +308,7 @@ rcc_gpio_attach(device_t dev)
RCC_WRITE(sc, RCC_GPIO_GP_LVL, sc->sc_output);
/* Attach the gpiobus. */
- sc->sc_busdev = gpiobus_attach_bus(dev);
+ sc->sc_busdev = gpiobus_add_bus(dev);
if (sc->sc_busdev == NULL) {
bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_io_rid,
sc->sc_io_res);
@@ -316,6 +316,7 @@ rcc_gpio_attach(device_t dev)
return (ENXIO);
}
+ bus_attach_children(dev);
return (0);
}
diff --git a/sys/dev/uart/uart_cpu_acpi.c b/sys/dev/uart/uart_cpu_acpi.c
index 7382c47a8db6..da77603f0093 100644
--- a/sys/dev/uart/uart_cpu_acpi.c
+++ b/sys/dev/uart/uart_cpu_acpi.c
@@ -44,23 +44,15 @@
#include <contrib/dev/acpica/include/accommon.h>
#include <contrib/dev/acpica/include/actables.h>
-static struct acpi_uart_compat_data *
+static struct acpi_spcr_compat_data *
uart_cpu_acpi_scan(uint8_t interface_type)
{
- struct acpi_uart_compat_data **cd, *curcd;
+ struct acpi_spcr_compat_data **cd, *curcd;
int i;
- SET_FOREACH(cd, uart_acpi_class_and_device_set) {
+ SET_FOREACH(cd, uart_acpi_spcr_class_set) {
curcd = *cd;
- for (i = 0; curcd[i].cd_hid != NULL; i++) {
- if (curcd[i].cd_port_subtype == interface_type)
- return (&curcd[i]);
- }
- }
-
- SET_FOREACH(cd, uart_acpi_class_set) {
- curcd = *cd;
- for (i = 0; curcd[i].cd_hid != NULL; i++) {
+ for (i = 0; curcd[i].cd_class != NULL; i++) {
if (curcd[i].cd_port_subtype == interface_type)
return (&curcd[i]);
}
@@ -143,7 +135,7 @@ uart_cpu_acpi_spcr(int devtype, struct uart_devinfo *di)
{
vm_paddr_t spcr_physaddr;
ACPI_TABLE_SPCR *spcr;
- struct acpi_uart_compat_data *cd;
+ struct acpi_spcr_compat_data *cd;
struct uart_class *class;
int error = ENXIO;
@@ -237,7 +229,7 @@ uart_cpu_acpi_dbg2(struct uart_devinfo *di)
ACPI_TABLE_DBG2 *dbg2;
ACPI_DBG2_DEVICE *dbg2_dev;
ACPI_GENERIC_ADDRESS *base_address;
- struct acpi_uart_compat_data *cd;
+ struct acpi_spcr_compat_data *cd;
struct uart_class *class;
int error;
bool found;
diff --git a/sys/dev/uart/uart_cpu_acpi.h b/sys/dev/uart/uart_cpu_acpi.h
index 94329e1f1349..218f643c7621 100644
--- a/sys/dev/uart/uart_cpu_acpi.h
+++ b/sys/dev/uart/uart_cpu_acpi.h
@@ -35,11 +35,18 @@
struct uart_class;
+struct acpi_spcr_compat_data {
+ struct uart_class *cd_class;
+ uint16_t cd_port_subtype;
+};
+SET_DECLARE(uart_acpi_spcr_class_set, struct acpi_spcr_compat_data);
+#define UART_ACPI_SPCR_CLASS(data) \
+ DATA_SET(uart_acpi_spcr_class_set, data)
+
struct acpi_uart_compat_data {
const char *cd_hid;
struct uart_class *cd_class;
- uint16_t cd_port_subtype;
int cd_regshft;
int cd_regiowidth;
int cd_rclk;
@@ -56,14 +63,6 @@ SET_DECLARE(uart_acpi_class_and_device_set, struct acpi_uart_compat_data);
#define UART_ACPI_CLASS_AND_DEVICE(data) \
DATA_SET(uart_acpi_class_and_device_set, data)
-/*
- * If your UART driver implements uart_class and custom device layer,
- * then use UART_ACPI_CLASS for its declaration
- */
-SET_DECLARE(uart_acpi_class_set, struct acpi_uart_compat_data);
-#define UART_ACPI_CLASS(data) \
- DATA_SET(uart_acpi_class_set, data)
-
/* Try to initialize UART device from ACPI tables */
int uart_cpu_acpi_setup(int devtype, struct uart_devinfo *di);
diff --git a/sys/dev/uart/uart_dev_ns8250.c b/sys/dev/uart/uart_dev_ns8250.c
index 0f19ede6d9df..c38d50e54ad8 100644
--- a/sys/dev/uart/uart_dev_ns8250.c
+++ b/sys/dev/uart/uart_dev_ns8250.c
@@ -492,24 +492,32 @@ UART_CLASS(uart_ns8250_class);
* XXX -- refactor out ACPI and FDT ifdefs
*/
#ifdef DEV_ACPI
+static struct acpi_spcr_compat_data acpi_spcr_compat_data[] = {
+ { &uart_ns8250_class, ACPI_DBG2_16550_COMPATIBLE },
+ { &uart_ns8250_class, ACPI_DBG2_16550_SUBSET },
+ { &uart_ns8250_class, ACPI_DBG2_16550_WITH_GAS },
+ { NULL, 0 },
+};
+UART_ACPI_SPCR_CLASS(acpi_spcr_compat_data);
+
static struct acpi_uart_compat_data acpi_compat_data[] = {
- {"AMD0020", &uart_ns8250_class, 0, 2, 0, 48000000, UART_F_BUSY_DETECT, "AMD / Synopsys Designware UART"},
- {"AMDI0020", &uart_ns8250_class, 0, 2, 0, 48000000, UART_F_BUSY_DETECT, "AMD / Synopsys Designware UART"},
- {"APMC0D08", &uart_ns8250_class, ACPI_DBG2_16550_COMPATIBLE, 2, 4, 0, 0, "APM compatible UART"},
- {"MRVL0001", &uart_ns8250_class, ACPI_DBG2_16550_SUBSET, 2, 0, 200000000, UART_F_BUSY_DETECT, "Marvell / Synopsys Designware UART"},
- {"SCX0006", &uart_ns8250_class, 0, 2, 0, 62500000, UART_F_BUSY_DETECT, "SynQuacer / Synopsys Designware UART"},
- {"HISI0031", &uart_ns8250_class, 0, 2, 0, 200000000, UART_F_BUSY_DETECT, "HiSilicon / Synopsys Designware UART"},
- {"INTC1006", &uart_ns8250_class, 0, 2, 0, 25000000, 0, "Intel ARM64 UART"},
- {"NXP0018", &uart_ns8250_class, 0, 0, 0, 350000000, UART_F_BUSY_DETECT, "NXP / Synopsys Designware UART"},
- {"PNP0500", &uart_ns8250_class, 0, 0, 0, 0, 0, "Standard PC COM port"},
- {"PNP0501", &uart_ns8250_class, 0, 0, 0, 0, 0, "16550A-compatible COM port"},
- {"PNP0502", &uart_ns8250_class, 0, 0, 0, 0, 0, "Multiport serial device (non-intelligent 16550)"},
- {"PNP0510", &uart_ns8250_class, 0, 0, 0, 0, 0, "Generic IRDA-compatible device"},
- {"PNP0511", &uart_ns8250_class, 0, 0, 0, 0, 0, "Generic IRDA-compatible device"},
- {"WACF004", &uart_ns8250_class, 0, 0, 0, 0, 0, "Wacom Tablet PC Screen"},
- {"WACF00E", &uart_ns8250_class, 0, 0, 0, 0, 0, "Wacom Tablet PC Screen 00e"},
- {"FUJ02E5", &uart_ns8250_class, 0, 0, 0, 0, 0, "Wacom Tablet at FuS Lifebook T"},
- {NULL, NULL, 0, 0 , 0, 0, 0, NULL},
+ {"AMD0020", &uart_ns8250_class, 2, 0, 48000000, UART_F_BUSY_DETECT, "AMD / Synopsys Designware UART"},
+ {"AMDI0020", &uart_ns8250_class, 2, 0, 48000000, UART_F_BUSY_DETECT, "AMD / Synopsys Designware UART"},
+ {"APMC0D08", &uart_ns8250_class, 2, 4, 0, 0, "APM compatible UART"},
+ {"MRVL0001", &uart_ns8250_class, 2, 0, 200000000, UART_F_BUSY_DETECT, "Marvell / Synopsys Designware UART"},
+ {"SCX0006", &uart_ns8250_class, 2, 0, 62500000, UART_F_BUSY_DETECT, "SynQuacer / Synopsys Designware UART"},
+ {"HISI0031", &uart_ns8250_class, 2, 0, 200000000, UART_F_BUSY_DETECT, "HiSilicon / Synopsys Designware UART"},
+ {"INTC1006", &uart_ns8250_class, 2, 0, 25000000, 0, "Intel ARM64 UART"},
+ {"NXP0018", &uart_ns8250_class, 0, 0, 350000000, UART_F_BUSY_DETECT, "NXP / Synopsys Designware UART"},
+ {"PNP0500", &uart_ns8250_class, 0, 0, 0, 0, "Standard PC COM port"},
+ {"PNP0501", &uart_ns8250_class, 0, 0, 0, 0, "16550A-compatible COM port"},
+ {"PNP0502", &uart_ns8250_class, 0, 0, 0, 0, "Multiport serial device (non-intelligent 16550)"},
+ {"PNP0510", &uart_ns8250_class, 0, 0, 0, 0, "Generic IRDA-compatible device"},
+ {"PNP0511", &uart_ns8250_class, 0, 0, 0, 0, "Generic IRDA-compatible device"},
+ {"WACF004", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet PC Screen"},
+ {"WACF00E", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet PC Screen 00e"},
+ {"FUJ02E5", &uart_ns8250_class, 0, 0, 0, 0, "Wacom Tablet at FuS Lifebook T"},
+ {NULL, NULL, 0 , 0, 0, 0, NULL},
};
UART_ACPI_CLASS_AND_DEVICE(acpi_compat_data);
#endif
diff --git a/sys/dev/uart/uart_dev_pl011.c b/sys/dev/uart/uart_dev_pl011.c
index a0d5a5b1c7e2..6afc693cd347 100644
--- a/sys/dev/uart/uart_dev_pl011.c
+++ b/sys/dev/uart/uart_dev_pl011.c
@@ -391,11 +391,19 @@ UART_FDT_CLASS_AND_DEVICE(fdt_compat_data);
#endif
#ifdef DEV_ACPI
+static struct acpi_spcr_compat_data acpi_spcr_compat_data[] = {
+ { &uart_pl011_class, ACPI_DBG2_ARM_PL011 },
+ { &uart_pl011_class, ACPI_DBG2_ARM_SBSA_GENERIC },
+ { &uart_pl011_class, ACPI_DBG2_ARM_SBSA_32BIT },
+ { NULL, 0 },
+};
+UART_ACPI_SPCR_CLASS(acpi_spcr_compat_data);
+
static struct acpi_uart_compat_data acpi_compat_data[] = {
- {"ARMH0011", &uart_pl011_class, ACPI_DBG2_ARM_PL011, 2, 0, 0, 0, "uart pl011"},
- {"ARMHB000", &uart_pl011_class, ACPI_DBG2_ARM_SBSA_GENERIC, 2, 0, 0, 0, "uart pl011"},
- {"ARMHB000", &uart_pl011_class, ACPI_DBG2_ARM_SBSA_32BIT, 2, 0, 0, 0, "uart pl011"},
- {NULL, NULL, 0, 0, 0, 0, 0, NULL},
+ {"ARMH0011", &uart_pl011_class, 2, 0, 0, 0, "uart pl011"},
+ {"ARMHB000", &uart_pl011_class, 2, 0, 0, 0, "uart pl011"},
+ {"ARMHB000", &uart_pl011_class, 2, 0, 0, 0, "uart pl011"},
+ {NULL, NULL, 0, 0, 0, 0, NULL},
};
UART_ACPI_CLASS_AND_DEVICE(acpi_compat_data);
#endif
diff --git a/sys/dev/usb/misc/cp2112.c b/sys/dev/usb/misc/cp2112.c
index d4776ca342cb..201a3ec51ce4 100644
--- a/sys/dev/usb/misc/cp2112.c
+++ b/sys/dev/usb/misc/cp2112.c
@@ -708,11 +708,12 @@ cp2112gpio_attach(device_t dev)
}
}
- sc->busdev = gpiobus_attach_bus(dev);
+ sc->busdev = gpiobus_add_bus(dev);
if (sc->busdev == NULL) {
- device_printf(dev, "gpiobus_attach_bus failed\n");
+ device_printf(dev, "gpiobus_add_bus failed\n");
goto detach;
}
+ bus_attach_children(dev);
return (0);
detach:
diff --git a/sys/dev/usb/net/if_ipheth.c b/sys/dev/usb/net/if_ipheth.c
index f70113c53eb4..cfa800707391 100644
--- a/sys/dev/usb/net/if_ipheth.c
+++ b/sys/dev/usb/net/if_ipheth.c
@@ -55,6 +55,7 @@
#include <net/if_var.h>
#include <dev/usb/usb.h>
+#include <dev/usb/usb_cdc.h>
#include <dev/usb/usbdi.h>
#include <dev/usb/usbdi_util.h>
#include "usbdevs.h"
@@ -81,6 +82,9 @@ static uether_fn_t ipheth_start;
static uether_fn_t ipheth_setmulti;
static uether_fn_t ipheth_setpromisc;
+static ipheth_consumer_t ipheth_consume_read;
+static ipheth_consumer_t ipheth_consume_read_ncm;
+
#ifdef USB_DEBUG
static int ipheth_debug = 0;
@@ -96,7 +100,31 @@ static const struct usb_config ipheth_config[IPHETH_N_TRANSFER] = {
.direction = UE_DIR_RX,
.frames = IPHETH_RX_FRAMES_MAX,
.bufsize = (IPHETH_RX_FRAMES_MAX * MCLBYTES),
- .flags = {.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,},
+ .flags = {.short_frames_ok = 1, .short_xfer_ok = 1, .ext_buffer = 1,},
+ .callback = ipheth_bulk_read_callback,
+ .timeout = 0, /* no timeout */
+ },
+
+ [IPHETH_BULK_TX] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_TX,
+ .frames = IPHETH_TX_FRAMES_MAX,
+ .bufsize = (IPHETH_TX_FRAMES_MAX * IPHETH_BUF_SIZE),
+ .flags = {.force_short_xfer = 1,},
+ .callback = ipheth_bulk_write_callback,
+ .timeout = IPHETH_TX_TIMEOUT,
+ },
+};
+
+static const struct usb_config ipheth_config_ncm[IPHETH_N_TRANSFER] = {
+ [IPHETH_BULK_RX] = {
+ .type = UE_BULK,
+ .endpoint = UE_ADDR_ANY,
+ .direction = UE_DIR_RX,
+ .frames = 1,
+ .bufsize = IPHETH_RX_NCM_BUF_SIZE,
+ .flags = {.short_frames_ok = 1, .short_xfer_ok = 1,},
.callback = ipheth_bulk_read_callback,
.timeout = 0, /* no timeout */
},
@@ -204,6 +232,21 @@ ipheth_get_mac_addr(struct ipheth_softc *sc)
return (0);
}
+static bool
+ipheth_enable_ncm(struct ipheth_softc *sc)
+{
+ struct usb_device_request req;
+
+ req.bmRequestType = UT_WRITE_VENDOR_INTERFACE;
+ req.bRequest = IPHETH_CMD_ENABLE_NCM;
+ USETW(req.wValue, 0);
+ req.wIndex[0] = sc->sc_iface_no;
+ req.wIndex[1] = 0;
+ USETW(req.wLength, 0);
+
+ return (usbd_do_request(sc->sc_ue.ue_udev, NULL, &req, NULL) == 0);
+}
+
static int
ipheth_probe(device_t dev)
{
@@ -221,6 +264,7 @@ ipheth_attach(device_t dev)
struct ipheth_softc *sc = device_get_softc(dev);
struct usb_ether *ue = &sc->sc_ue;
struct usb_attach_arg *uaa = device_get_ivars(dev);
+ const struct usb_config *config;
int error;
sc->sc_iface_no = uaa->info.bIfaceIndex;
@@ -235,18 +279,29 @@ ipheth_attach(device_t dev)
device_printf(dev, "Cannot set alternate setting\n");
goto detach;
}
- error = usbd_transfer_setup(uaa->device, &sc->sc_iface_no,
- sc->sc_xfer, ipheth_config, IPHETH_N_TRANSFER, sc, &sc->sc_mtx);
- if (error) {
- device_printf(dev, "Cannot setup USB transfers\n");
- goto detach;
- }
+
ue->ue_sc = sc;
ue->ue_dev = dev;
ue->ue_udev = uaa->device;
ue->ue_mtx = &sc->sc_mtx;
ue->ue_methods = &ipheth_ue_methods;
+ if (ipheth_enable_ncm(sc)) {
+ config = ipheth_config_ncm;
+ sc->is_ncm = true;
+ sc->consume = &ipheth_consume_read_ncm;
+ } else {
+ config = ipheth_config;
+ sc->consume = &ipheth_consume_read;
+ }
+
+ error = usbd_transfer_setup(uaa->device, &sc->sc_iface_no, sc->sc_xfer,
+ config, IPHETH_N_TRANSFER, sc, &sc->sc_mtx);
+ if (error) {
+ device_printf(dev, "Cannot setup USB transfers\n");
+ goto detach;
+ }
+
error = ipheth_get_mac_addr(sc);
if (error) {
device_printf(dev, "Cannot get MAC address\n");
@@ -389,12 +444,9 @@ ipheth_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error)
int actlen;
int aframes;
- usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
-
- DPRINTFN(1, "\n");
-
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
+ usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
DPRINTFN(11, "transfer complete: %u bytes in %u frames\n",
actlen, aframes);
@@ -471,53 +523,40 @@ ipheth_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
uint8_t x;
int actlen;
int aframes;
- int len;
-
- usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
-
+ usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL);
DPRINTF("received %u bytes in %u frames\n", actlen, aframes);
- for (x = 0; x != aframes; x++) {
- m = sc->sc_rx_buf[x];
- sc->sc_rx_buf[x] = NULL;
- len = usbd_xfer_frame_len(xfer, x);
-
- if (len < (int)(sizeof(struct ether_header) +
- IPHETH_RX_ADJ)) {
- m_freem(m);
- continue;
- }
-
- m_adj(m, IPHETH_RX_ADJ);
-
- /* queue up mbuf */
- uether_rxmbuf(&sc->sc_ue, m, len - IPHETH_RX_ADJ);
- }
+ for (x = 0; x != aframes; x++)
+ sc->consume(xfer, x);
/* FALLTHROUGH */
case USB_ST_SETUP:
-
- for (x = 0; x != IPHETH_RX_FRAMES_MAX; x++) {
- if (sc->sc_rx_buf[x] == NULL) {
- m = uether_newbuf();
- if (m == NULL)
- goto tr_stall;
-
- /* cancel alignment for ethernet */
- m_adj(m, ETHER_ALIGN);
-
- sc->sc_rx_buf[x] = m;
- } else {
- m = sc->sc_rx_buf[x];
+ if (!sc->is_ncm) {
+ for (x = 0; x != IPHETH_RX_FRAMES_MAX; x++) {
+ if (sc->sc_rx_buf[x] == NULL) {
+ m = uether_newbuf();
+ if (m == NULL)
+ goto tr_stall;
+
+ /* cancel alignment for ethernet */
+ m_adj(m, ETHER_ALIGN);
+
+ sc->sc_rx_buf[x] = m;
+ } else {
+ m = sc->sc_rx_buf[x];
+ }
+ usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len);
}
-
- usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len);
+ usbd_xfer_set_frames(xfer, x);
+ } else {
+ usbd_xfer_set_frame_len(xfer, 0,
+ IPHETH_RX_NCM_BUF_SIZE);
+ usbd_xfer_set_frames(xfer, 1);
}
- /* set number of frames and start hardware */
- usbd_xfer_set_frames(xfer, x);
+
usbd_transfer_submit(xfer);
/* flush any received frames */
uether_rxflush(&sc->sc_ue);
@@ -539,3 +578,86 @@ ipheth_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error)
break;
}
}
+
+static void
+ipheth_consume_read(struct usb_xfer *xfer, int x)
+{
+ struct ipheth_softc *sc = usbd_xfer_softc(xfer);
+ struct mbuf *m = sc->sc_rx_buf[x];
+ int len;
+
+ sc->sc_rx_buf[x] = NULL;
+ len = usbd_xfer_frame_len(xfer, x);
+
+ if (len < (int)(sizeof(struct ether_header) + IPHETH_RX_ADJ)) {
+ m_freem(m);
+ return;
+ }
+
+ m_adj(m, IPHETH_RX_ADJ);
+
+ /* queue up mbuf */
+ uether_rxmbuf(&sc->sc_ue, m, len - IPHETH_RX_ADJ);
+}
+
+static void
+ipheth_consume_read_ncm(struct usb_xfer *xfer, int x)
+{
+ struct ipheth_softc *sc = usbd_xfer_softc(xfer);
+ struct usb_page_cache *pc = usbd_xfer_get_frame(xfer, 0);
+ struct ncm_data_cache ncm;
+ if_t ifp = uether_getifp(&sc->sc_ue);
+ struct mbuf *new_buf;
+ int i, actlen;
+ uint16_t dp_offset, dp_len;
+
+ usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
+
+ if (actlen < IPHETH_NCM_HEADER_SIZE)
+ return;
+
+ usbd_copy_out(pc, 0, &ncm.hdr, sizeof(ncm.hdr));
+
+ if (UGETDW(ncm.hdr.dwSignature) != 0x484D434E)
+ return;
+
+ /* Dpt follows the hdr on iOS */
+ if (UGETW(ncm.hdr.wDptIndex) != (int)(sizeof(struct usb_ncm16_hdr)))
+ return;
+
+ usbd_copy_out(pc, UGETW(ncm.hdr.wDptIndex), &ncm.dpt, sizeof(ncm.dpt));
+
+ if (UGETDW(ncm.dpt.dwSignature) != 0x304D434E)
+ return;
+
+ usbd_copy_out(pc, UGETW(ncm.hdr.wDptIndex) + sizeof(ncm.dpt), &ncm.dp,
+ sizeof(ncm.dp));
+
+ for (i = 0; i < IPHETH_NCM_DPT_DP_NUM; ++i) {
+ dp_offset = UGETW(ncm.dp[i].wFrameIndex);
+ dp_len = UGETW(ncm.dp[i].wFrameLength);
+
+ /* (3.3.1 USB CDC NCM spec v1.0) */
+ if (dp_offset == 0 && dp_len == 0)
+ break;
+
+ if (dp_offset < IPHETH_NCM_HEADER_SIZE || dp_offset >= actlen ||
+ actlen < (dp_len + dp_offset) ||
+ dp_len < sizeof(struct ether_header)) {
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ continue;
+ }
+ if (dp_len > (MCLBYTES - ETHER_ALIGN)) {
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
+ continue;
+ }
+
+ new_buf = uether_newbuf();
+ if (new_buf == NULL) {
+ if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1);
+ continue;
+ }
+ usbd_copy_out(pc, dp_offset, new_buf->m_data, dp_len);
+ uether_rxmbuf(&sc->sc_ue, new_buf, dp_len);
+ }
+}
diff --git a/sys/dev/usb/net/if_iphethvar.h b/sys/dev/usb/net/if_iphethvar.h
index 203bb96b6f22..d637e8f67d01 100644
--- a/sys/dev/usb/net/if_iphethvar.h
+++ b/sys/dev/usb/net/if_iphethvar.h
@@ -41,6 +41,7 @@
#define IPHETH_BUF_SIZE 1514
#define IPHETH_TX_TIMEOUT 5000 /* ms */
+#define IPHETH_RX_NCM_BUF_SIZE 65536
#define IPHETH_RX_FRAMES_MAX 1
#define IPHETH_TX_FRAMES_MAX 8
@@ -55,10 +56,20 @@
#define IPHETH_CTRL_TIMEOUT 5000 /* ms */
#define IPHETH_CMD_GET_MACADDR 0x00
+#define IPHETH_CMD_ENABLE_NCM 0x04
#define IPHETH_CMD_CARRIER_CHECK 0x45
#define IPHETH_CARRIER_ON 0x04
+#define IPHETH_NCM_DPT_DP_NUM 22
+#define IPHETH_NCM_DPT_HEADER_SIZE \
+ (sizeof(struct usb_ncm16_dpt) + \
+ IPHETH_NCM_DPT_DP_NUM * sizeof(struct usb_ncm16_dp))
+#define IPHETH_NCM_HEADER_SIZE \
+ (sizeof(struct usb_ncm16_hdr) + IPHETH_NCM_DPT_HEADER_SIZE)
+
+typedef void (ipheth_consumer_t)(struct usb_xfer *xfer, int idx);
+
enum {
IPHETH_BULK_TX,
IPHETH_BULK_RX,
@@ -76,6 +87,16 @@ struct ipheth_softc {
uint8_t sc_data[IPHETH_CTRL_BUF_SIZE];
uint8_t sc_iface_no;
uint8_t sc_carrier_on;
+
+ bool is_ncm;
+
+ ipheth_consumer_t *consume;
+};
+
+struct ncm_data_cache {
+ struct usb_ncm16_hdr hdr;
+ struct usb_ncm16_dpt dpt;
+ struct usb_ncm16_dp dp[IPHETH_NCM_DPT_DP_NUM];
};
#define IPHETH_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
diff --git a/sys/dev/watchdog/watchdog.c b/sys/dev/watchdog/watchdog.c
index e6b6dc1eac70..e1b2e08c3f10 100644
--- a/sys/dev/watchdog/watchdog.c
+++ b/sys/dev/watchdog/watchdog.c
@@ -50,11 +50,20 @@
#include <sys/syscallsubr.h> /* kern_clock_gettime() */
-static int wd_set_pretimeout(int newtimeout, int disableiftoolong);
+#ifdef COMPAT_FREEBSD14
+#define WDIOCPATPAT_14 _IOW('W', 42, u_int) /* pat the watchdog */
+#define WDIOC_SETTIMEOUT_14 _IOW('W', 43, int) /* set/reset the timer */
+#define WDIOC_GETTIMEOUT_14 _IOR('W', 44, int) /* get total timeout */
+#define WDIOC_GETTIMELEFT_14 _IOR('W', 45, int) /* get time left */
+#define WDIOC_GETPRETIMEOUT_14 _IOR('W', 46, int) /* get the pre-timeout */
+#define WDIOC_SETPRETIMEOUT_14 _IOW('W', 47, int) /* set the pre-timeout */
+#endif
+
+static int wd_set_pretimeout(sbintime_t newtimeout, int disableiftoolong);
static void wd_timeout_cb(void *arg);
static struct callout wd_pretimeo_handle;
-static int wd_pretimeout;
+static sbintime_t wd_pretimeout;
static int wd_pretimeout_act = WD_SOFT_LOG;
static struct callout wd_softtimeo_handle;
@@ -63,6 +72,8 @@ static int wd_softtimer; /* true = use softtimer instead of hardware
static int wd_softtimeout_act = WD_SOFT_LOG; /* action for the software timeout */
static struct cdev *wd_dev;
+static volatile sbintime_t wd_last_sbt; /* last timeout value (sbt) */
+static sbintime_t wd_last_sbt_sysctl; /* last timeout value (sbt) */
static volatile u_int wd_last_u; /* last timeout value set by kern_do_pat */
static u_int wd_last_u_sysctl; /* last timeout value set by kern_do_pat */
static u_int wd_last_u_sysctl_secs; /* wd_last_u in seconds */
@@ -73,6 +84,8 @@ SYSCTL_UINT(_hw_watchdog, OID_AUTO, wd_last_u, CTLFLAG_RD,
&wd_last_u_sysctl, 0, "Watchdog last update time");
SYSCTL_UINT(_hw_watchdog, OID_AUTO, wd_last_u_secs, CTLFLAG_RD,
&wd_last_u_sysctl_secs, 0, "Watchdog last update time");
+SYSCTL_SBINTIME_MSEC(_hw_watchdog, OID_AUTO, wd_last_msecs, CTLFLAG_RD,
+ &wd_last_sbt_sysctl, "Watchdog last update time (milliseconds)");
static int wd_lastpat_valid = 0;
static time_t wd_lastpat = 0; /* when the watchdog was last patted */
@@ -80,105 +93,94 @@ static time_t wd_lastpat = 0; /* when the watchdog was last patted */
/* Hook for external software watchdog to register for use if needed */
void (*wdog_software_attach)(void);
-static void
-pow2ns_to_ts(int pow2ns, struct timespec *ts)
+/* Legacy interface to watchdog. */
+int
+wdog_kern_pat(u_int utim)
{
- uint64_t ns;
+ sbintime_t sbt;
- ns = 1ULL << pow2ns;
- ts->tv_sec = ns / 1000000000ULL;
- ts->tv_nsec = ns % 1000000000ULL;
-}
+ if ((utim & WD_LASTVAL) != 0 && (utim & WD_INTERVAL) > 0)
+ return (EINVAL);
-static int
-pow2ns_to_ticks(int pow2ns)
-{
- struct timeval tv;
- struct timespec ts;
+ if ((utim & WD_LASTVAL) != 0) {
+ return (wdog_control(WD_CTRL_RESET));
+ }
- pow2ns_to_ts(pow2ns, &ts);
- TIMESPEC_TO_TIMEVAL(&tv, &ts);
- return (tvtohz(&tv));
+ utim &= WD_INTERVAL;
+ if (utim == WD_TO_NEVER)
+ sbt = 0;
+ else
+ sbt = nstosbt(1 << utim);
+
+ return (wdog_kern_pat_sbt(sbt));
}
-static int
-seconds_to_pow2ns(int seconds)
+int
+wdog_control(int ctrl)
{
- uint64_t power;
- uint64_t ns;
- uint64_t shifted;
-
- ns = ((uint64_t)seconds) * 1000000000ULL;
- power = flsll(ns);
- shifted = 1ULL << power;
- if (shifted <= ns) {
- power++;
+ /* Disable takes precedence */
+ if (ctrl == WD_CTRL_DISABLE) {
+ wdog_kern_pat(0);
}
- return (power);
+
+ if ((ctrl & WD_CTRL_RESET) != 0) {
+ wdog_kern_pat_sbt(wd_last_sbt);
+ } else if ((ctrl & WD_CTRL_ENABLE) != 0) {
+ wdog_kern_pat_sbt(wd_last_sbt);
+ }
+
+ return (0);
}
int
-wdog_kern_pat(u_int utim)
+wdog_kern_pat_sbt(sbintime_t sbt)
{
- int error;
- static int first = 1;
-
- if ((utim & WD_LASTVAL) != 0 && (utim & WD_INTERVAL) > 0)
- return (EINVAL);
-
- if ((utim & WD_LASTVAL) != 0) {
- /*
- * if WD_LASTVAL is set, fill in the bits for timeout
- * from the saved value in wd_last_u.
- */
- MPASS((wd_last_u & ~WD_INTERVAL) == 0);
- utim &= ~WD_LASTVAL;
- utim |= wd_last_u;
- } else {
- /*
- * Otherwise save the new interval.
- * This can be zero (to disable the watchdog)
- */
- wd_last_u = (utim & WD_INTERVAL);
+ sbintime_t error_sbt = 0;
+ int pow2ns = 0;
+ int error = 0;
+ static bool first = true;
+
+ /* legacy uses power-of-2-nanoseconds time. */
+ if (sbt != 0) {
+ pow2ns = flsl(sbttons(sbt));
+ }
+ if (wd_last_sbt != sbt) {
+ wd_last_u = pow2ns;
wd_last_u_sysctl = wd_last_u;
- wd_last_u_sysctl_secs = pow2ns_to_ticks(wd_last_u) / hz;
+ wd_last_u_sysctl_secs = sbt / SBT_1S;
+
+ wd_last_sbt = sbt;
}
- if ((utim & WD_INTERVAL) == WD_TO_NEVER) {
- utim = 0;
- /* Assume all is well; watchdog signals failure. */
- error = 0;
- } else {
- /* Assume no watchdog available; watchdog flags success */
+ if (sbt != 0)
error = EOPNOTSUPP;
- }
+
if (wd_softtimer) {
- if (utim == 0) {
+ if (sbt == 0) {
callout_stop(&wd_softtimeo_handle);
} else {
- (void) callout_reset(&wd_softtimeo_handle,
- pow2ns_to_ticks(utim), wd_timeout_cb, "soft");
+ (void) callout_reset_sbt(&wd_softtimeo_handle,
+ sbt, 0, wd_timeout_cb, "soft", 0);
}
error = 0;
} else {
- EVENTHANDLER_INVOKE(watchdog_list, utim, &error);
+ EVENTHANDLER_INVOKE(watchdog_sbt_list, sbt, &error_sbt, &error);
+ EVENTHANDLER_INVOKE(watchdog_list, pow2ns, &error);
}
/*
- * If we no hardware watchdog responded, we have not tried to
+ * If no hardware watchdog responded, we have not tried to
* attach an external software watchdog, and one is available,
* attach it now and retry.
*/
- if (error == EOPNOTSUPP && first && *wdog_software_attach != NULL) {
+ if (error == EOPNOTSUPP && first && wdog_software_attach != NULL) {
(*wdog_software_attach)();
- EVENTHANDLER_INVOKE(watchdog_list, utim, &error);
+ EVENTHANDLER_INVOKE(watchdog_sbt_list, sbt, &error_sbt, &error);
+ EVENTHANDLER_INVOKE(watchdog_list, pow2ns, &error);
}
- first = 0;
+ first = false;
+ /* TODO: Print a (rate limited?) warning if error_sbt is too far away */
wd_set_pretimeout(wd_pretimeout, true);
- /*
- * If we were able to arm/strobe the watchdog, then
- * update the last time it was strobed for WDIOC_GETTIMELEFT
- */
if (!error) {
struct timespec ts;
@@ -189,6 +191,7 @@ wdog_kern_pat(u_int utim)
wd_lastpat_valid = 1;
}
}
+
return (error);
}
@@ -265,16 +268,14 @@ wd_timeout_cb(void *arg)
* current actual watchdog timeout.
*/
static int
-wd_set_pretimeout(int newtimeout, int disableiftoolong)
+wd_set_pretimeout(sbintime_t newtimeout, int disableiftoolong)
{
- u_int utime;
- struct timespec utime_ts;
- int timeout_ticks;
+ sbintime_t utime;
+ sbintime_t timeout_left;
- utime = wdog_kern_last_timeout();
- pow2ns_to_ts(utime, &utime_ts);
+ utime = wdog_kern_last_timeout_sbt();
/* do not permit a pre-timeout >= than the timeout. */
- if (newtimeout >= utime_ts.tv_sec) {
+ if (newtimeout >= utime) {
/*
* If 'disableiftoolong' then just fall through
* so as to disable the pre-watchdog
@@ -292,7 +293,7 @@ wd_set_pretimeout(int newtimeout, int disableiftoolong)
return 0;
}
- timeout_ticks = pow2ns_to_ticks(utime) - (hz*newtimeout);
+ timeout_left = utime - newtimeout;
#if 0
printf("wd_set_pretimeout: "
"newtimeout: %d, "
@@ -306,8 +307,8 @@ wd_set_pretimeout(int newtimeout, int disableiftoolong)
#endif
/* We determined the value is sane, so reset the callout */
- (void) callout_reset(&wd_pretimeo_handle,
- timeout_ticks, wd_timeout_cb, "pre");
+ (void) callout_reset_sbt(&wd_pretimeo_handle,
+ timeout_left, 0, wd_timeout_cb, "pre", 0);
wd_pretimeout = newtimeout;
return 0;
}
@@ -316,6 +317,7 @@ static int
wd_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
int flags __unused, struct thread *td)
{
+ sbintime_t sb;
u_int u;
time_t timeleft;
int error;
@@ -351,29 +353,55 @@ wd_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data,
error = EINVAL;
}
break;
- case WDIOC_GETPRETIMEOUT:
- *(int *)data = (int)wd_pretimeout;
+#ifdef COMPAT_FREEBSD14
+ case WDIOC_GETPRETIMEOUT_14:
+ *(int *)data = (int)(wd_pretimeout / SBT_1S);
break;
- case WDIOC_SETPRETIMEOUT:
- error = wd_set_pretimeout(*(int *)data, false);
+ case WDIOC_SETPRETIMEOUT_14:
+ error = wd_set_pretimeout(*(int *)data * SBT_1S, false);
break;
- case WDIOC_GETTIMELEFT:
+ case WDIOC_GETTIMELEFT_14:
error = wd_get_time_left(td, &timeleft);
if (error)
break;
*(int *)data = (int)timeleft;
break;
- case WDIOC_SETTIMEOUT:
+ case WDIOC_SETTIMEOUT_14:
u = *(u_int *)data;
- error = wdog_kern_pat(seconds_to_pow2ns(u));
+ error = wdog_kern_pat_sbt(mstosbt(u * 1000ULL));
break;
- case WDIOC_GETTIMEOUT:
+ case WDIOC_GETTIMEOUT_14:
u = wdog_kern_last_timeout();
*(u_int *)data = u;
break;
- case WDIOCPATPAT:
+ case WDIOCPATPAT_14:
error = wd_ioctl_patpat(data);
break;
+#endif
+
+ /* New API */
+ case WDIOC_CONTROL:
+ wdog_control(*(int *)data);
+ break;
+ case WDIOC_SETTIMEOUT:
+ sb = *(sbintime_t *)data;
+ error = wdog_kern_pat_sbt(sb);
+ break;
+ case WDIOC_GETTIMEOUT:
+ *(sbintime_t *)data = wdog_kern_last_timeout_sbt();
+ break;
+ case WDIOC_GETTIMELEFT:
+ error = wd_get_time_left(td, &timeleft);
+ if (error)
+ break;
+ *(sbintime_t *)data = (sbintime_t)timeleft * SBT_1S;
+ break;
+ case WDIOC_GETPRETIMEOUT:
+ *(sbintime_t *)data = wd_pretimeout;
+ break;
+ case WDIOC_SETPRETIMEOUT:
+ error = wd_set_pretimeout(*(sbintime_t *)data, false);
+ break;
default:
error = ENOIOCTL;
break;
@@ -392,6 +420,12 @@ wdog_kern_last_timeout(void)
return (wd_last_u);
}
+sbintime_t
+wdog_kern_last_timeout_sbt(void)
+{
+ return (wd_last_sbt);
+}
+
static struct cdevsw wd_cdevsw = {
.d_version = D_VERSION,
.d_ioctl = wd_ioctl,