From: kettenis Date: Sun, 23 Jul 2023 11:42:44 +0000 (+0000) Subject: Prevent spurious connection events after resume by caching the current X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=23d6429a03bae5a80cf2ced691eaaced32e41aa8;p=openbsd Prevent spurious connection events after resume by caching the current plug state and comparing it with the current plug state when we receive in interrupt. Only call the connect/disconnect callbacks registered for the port if the state really changed. This prevents an spurious attach/detach/attach sequence when resuming with a USB device connected. ok patrick@ --- diff --git a/sys/dev/fdt/tipd.c b/sys/dev/fdt/tipd.c index a1c7147aaaa..5d5ad2e13de 100644 --- a/sys/dev/fdt/tipd.c +++ b/sys/dev/fdt/tipd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tipd.c,v 1.2 2023/07/17 17:50:22 kettenis Exp $ */ +/* $OpenBSD: tipd.c,v 1.3 2023/07/23 11:42:44 kettenis Exp $ */ /* * Copyright (c) 2022 Mark Kettenis * @@ -42,6 +42,7 @@ #define TPS_SYSTEM_POWER_STATE 0x20 #define TPS_SYSTEM_POWER_STATE_S0 0 #define TPS_SYSTEM_POWER_STATE_S5 5 +#define TPS_POWER_STATUS 0x3f #define TPS_CMD(s) ((s[3] << 24) | (s[2] << 16) | (s[1] << 8) | s[0]) @@ -59,6 +60,7 @@ struct tipd_softc { void *sc_ih; struct device_ports sc_ports; + uint32_t sc_status; }; int tipd_match(struct device *, void *, void *); @@ -110,6 +112,7 @@ tipd_attach(struct device *parent, struct device *self, void *aux) printf("\n"); + tipd_read_4(sc, TPS_STATUS, &sc->sc_status); tipd_write_8(sc, TPS_INT_MASK_1, CD_INT_PLUG_EVENT); node = OF_getnodebyname(node, "connector"); @@ -127,6 +130,9 @@ tipd_activate(struct device *self, int act) int error; switch (act) { + case DVACT_QUIESCE: + tipd_write_8(sc, TPS_INT_MASK_1, 0); + break; case DVACT_SUSPEND: state = TPS_SYSTEM_POWER_STATE_S5; error = tipd_exec(sc, "SSPS", &state, sizeof(state), NULL, 0); @@ -139,6 +145,10 @@ tipd_activate(struct device *self, int act) if (error) printf("%s: powerup failed\n", sc->sc_dev.dv_xname); break; + case DVACT_WAKEUP: + tipd_read_4(sc, TPS_STATUS, &sc->sc_status); + tipd_write_8(sc, TPS_INT_MASK_1, CD_INT_PLUG_EVENT); + break; } return 0; @@ -197,11 +207,19 @@ tipd_intr(void *arg) error = tipd_read_4(sc, TPS_STATUS, &status); if (error) goto fail; - - if (status & TPS_STATUS_PLUG_PRESENT) - tipd_connect(sc); - else - tipd_disconnect(sc); + + /* + * We may get a spurious plug event upon resume. Make + * sure we only signal a new connection when the plug + * present state really changed. + */ + if ((status ^ sc->sc_status) & TPS_STATUS_PLUG_PRESENT) { + if (status & TPS_STATUS_PLUG_PRESENT) + tipd_connect(sc); + else + tipd_disconnect(sc); + sc->sc_status = status; + } } fail: