diff --git a/share/man/man4/psm.4 b/share/man/man4/psm.4 index ad4f5f24d92d..2324598c2848 100644 --- a/share/man/man4/psm.4 +++ b/share/man/man4/psm.4 @@ -26,7 +26,7 @@ .\" .\" $FreeBSD$ .\" -.Dd September 26, 2016 +.Dd June 2, 2020 .Dt PSM 4 .Os .Sh NAME @@ -361,6 +361,15 @@ the sysctl with the same name and by restarting .Xr moused 8 using .Pa /etc/rc.d/moused . +.Pp +Active multiplexing support can be disabled by setting +.Va hw.psm.mux_disabled +to +.Em 1 +at boot-time. +This will prevent +.Nm +from enabling active multiplexing mode needed for some Synaptics touchpads. .Sh IOCTLS There are a few .Xr ioctl 2 diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c index a8384b370f6c..f7e94b474cb9 100644 --- a/sys/dev/atkbdc/psm.c +++ b/sys/dev/atkbdc/psm.c @@ -517,6 +517,7 @@ static int verbose = PSM_DEBUG; static int synaptics_support = 1; static int trackpoint_support = 1; static int elantech_support = 1; +static int mux_disabled = 0; /* for backward compatibility */ #define OLD_MOUSE_GETHWINFO _IOR('M', 1, old_mousehw_t) @@ -2989,6 +2990,9 @@ SYSCTL_INT(_hw_psm, OID_AUTO, trackpoint_support, CTLFLAG_RDTUN, SYSCTL_INT(_hw_psm, OID_AUTO, elantech_support, CTLFLAG_RDTUN, &elantech_support, 0, "Enable support for Elantech touchpads"); +SYSCTL_INT(_hw_psm, OID_AUTO, mux_disabled, CTLFLAG_RDTUN, + &mux_disabled, 0, "Disable active multiplexing"); + static void psmintr(void *arg) { @@ -6293,6 +6297,9 @@ enable_synaptics_mux(struct psm_softc *sc, enum probearg arg) int active_ports_count = 0; int active_ports_mask = 0; + if (mux_disabled != 0) + return (FALSE); + version = enable_aux_mux(kbdc); if (version == -1) return (FALSE); @@ -6330,6 +6337,21 @@ enable_synaptics_mux(struct psm_softc *sc, enum probearg arg) /* IRQ handler does not support active multiplexing mode */ disable_aux_mux(kbdc); + /* Is MUX still alive after switching back to legacy mode? */ + if (!enable_aux_dev(kbdc) || !disable_aux_dev(kbdc)) { + /* + * On some laptops e.g. Lenovo X121e dead AUX MUX can be + * brought back to life with resetting of keyboard. + */ + reset_kbd(kbdc); + if (!enable_aux_dev(kbdc) || !disable_aux_dev(kbdc)) { + printf("psm%d: AUX MUX hang detected!\n", sc->unit); + printf("Consider adding hw.psm.mux_disabled=1 to " + "loader tunables\n"); + } + } + empty_both_buffers(kbdc, 10); /* remove stray data if any */ + return (probe); }